@trackunit/filters-asset-filter-definitions 1.11.116 → 1.12.4

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.
Files changed (34) hide show
  1. package/index.cjs.js +444 -161
  2. package/index.esm.js +445 -166
  3. package/package.json +18 -18
  4. package/src/defaultFilters/defaults/DeviceHealthIssueCategoryFilter/DeviceHealthIssueCategoryFilter.d.ts +9 -0
  5. package/src/defaultFilters/defaults/DeviceHealthIssueCategoryFilter/getHealthCategoryEnumWithFallback/getHealthCategoryEnumWithFallback.d.ts +8 -0
  6. package/src/defaultFilters/defaults/DeviceHealthIssueCategoryFilter/useDeviceHealthIssueCategoryDisplayNames/useDeviceHealthIssueCategoryDisplayNames.d.ts +7 -0
  7. package/src/defaultFilters/defaults/DeviceHealthIssueCategoryFilter/useDeviceHealthIssueCategoryFilter.d.ts +7 -0
  8. package/src/defaultFilters/defaults/DeviceHealthIssueTypeFilter/DeviceHealthIssueTypeFilter.d.ts +9 -0
  9. package/src/defaultFilters/defaults/DeviceHealthIssueTypeFilter/getHealthTypeEnumWithFallback/getHealthTypeEnumWithFallback.d.ts +8 -0
  10. package/src/defaultFilters/defaults/DeviceHealthIssueTypeFilter/useDeviceHealthIssueTypeDisplayNames/useDeviceHealthIssueTypeDisplayNames.d.ts +7 -0
  11. package/src/defaultFilters/defaults/DeviceHealthIssueTypeFilter/useDeviceHealthIssueTypeFilter.d.ts +7 -0
  12. package/src/defaultFilters/defaults/area/AreaFilter.d.ts +4 -11
  13. package/src/defaultFilters/defaults/index.d.ts +2 -0
  14. package/src/generated/graphql-api/gql.d.ts +14 -0
  15. package/src/generated/graphql-api/graphql.d.ts +38 -0
  16. package/src/generated/graphql-api/mock.d.ts +6 -0
  17. package/src/hooks/useDefaultAssetFilterBarDefinition.d.ts +3 -5
  18. package/src/translation.d.ts +2 -2
  19. package/translation.cjs12.js +1 -1
  20. package/translation.cjs13.js +1 -1
  21. package/translation.cjs14.js +1 -1
  22. package/translation.cjs15.js +1 -1
  23. package/translation.cjs17.js +1 -1
  24. package/translation.cjs3.js +1 -1
  25. package/translation.cjs5.js +1 -1
  26. package/translation.cjs8.js +1 -1
  27. package/translation.esm12.js +1 -1
  28. package/translation.esm13.js +1 -1
  29. package/translation.esm14.js +1 -1
  30. package/translation.esm15.js +1 -1
  31. package/translation.esm17.js +1 -1
  32. package/translation.esm3.js +1 -1
  33. package/translation.esm5.js +1 -1
  34. package/translation.esm8.js +1 -1
package/index.cjs.js CHANGED
@@ -12,9 +12,9 @@ var reactFilterComponents = require('@trackunit/react-filter-components');
12
12
  var reactFormComponents = require('@trackunit/react-form-components');
13
13
  var utilizationIndicator = require('@trackunit/utilization-indicator');
14
14
  var geoJsonUtils = require('@trackunit/geo-json-utils');
15
+ var zod = require('zod');
15
16
  var reactComponents = require('@trackunit/react-components');
16
17
  var stringTs = require('string-ts');
17
- var zod = require('zod');
18
18
  var sharedUtils = require('@trackunit/shared-utils');
19
19
  var translationsMachineType = require('@trackunit/translations-machine-type');
20
20
  var criticalityIndicator = require('@trackunit/criticality-indicator');
@@ -65,6 +65,20 @@ var defaultTranslations = {
65
65
  "assetFilters.criticality.CRITICAL": "Critical",
66
66
  "assetFilters.criticality.LOW": "Low",
67
67
  "assetFilters.criticality.NONE": "Good",
68
+ "assetFilters.deviceHealthIssueCategories": "Issue Categories",
69
+ "assetFilters.deviceHealthIssueCategory.coverageIssues": "Coverage",
70
+ "assetFilters.deviceHealthIssueCategory.deviceBatteryIssues": "Device battery",
71
+ "assetFilters.deviceHealthIssueCategory.installAndConfigurationHealth": "Install and configuration",
72
+ "assetFilters.deviceHealthIssueCategory.nonReportingUnit": "Non reporting devices",
73
+ "assetFilters.deviceHealthIssueType.dataNotReceived": "Data not received",
74
+ "assetFilters.deviceHealthIssueType.installationValidationMissing": "Installation validation missing",
75
+ "assetFilters.deviceHealthIssueType.lowCellularCoverage": "Low cellular coverage",
76
+ "assetFilters.deviceHealthIssueType.lowDeviceBatteryVoltage": "Low device battery voltage",
77
+ "assetFilters.deviceHealthIssueType.lowDeviceInputVoltage": "Low device input voltage",
78
+ "assetFilters.deviceHealthIssueType.lowGpsCoverage": "Low GPS coverage",
79
+ "assetFilters.deviceHealthIssueType.noCanDataConfiguration": "No CAN data",
80
+ "assetFilters.deviceHealthIssueType.operatingHours": "Unusual operating hours",
81
+ "assetFilters.deviceHealthIssueTypes": "Issue Types",
68
82
  "assetFilters.followedFilter.label": "Followed",
69
83
  "assetFilters.hourIntervalFilter.label": "Hour interval",
70
84
  "assetFilters.lastSeenFilter.anytime": "Any time",
@@ -448,6 +462,22 @@ const assetCriticalityState = {
448
462
  LOW: "LOW",
449
463
  NONE: "NONE",
450
464
  };
465
+ const fleetDataHealthIssueCategory = {
466
+ COVERAGE_ISSUES: "COVERAGE_ISSUES",
467
+ DEVICE_BATTERY_ISSUES: "DEVICE_BATTERY_ISSUES",
468
+ INSTALL_AND_CONFIGURATION_HEALTH: "INSTALL_AND_CONFIGURATION_HEALTH",
469
+ NON_REPORTING_UNIT: "NON_REPORTING_UNIT",
470
+ };
471
+ const fleetDataHealthIssueType = {
472
+ DATA_NOT_RECEIVED: "DATA_NOT_RECEIVED",
473
+ INSTALLATION_VALIDATION_MISSING: "INSTALLATION_VALIDATION_MISSING",
474
+ LOW_CELLULAR_COVERAGE: "LOW_CELLULAR_COVERAGE",
475
+ LOW_DEVICE_BATTERY_VOLTAGE: "LOW_DEVICE_BATTERY_VOLTAGE",
476
+ LOW_DEVICE_INPUT_VOLTAGE: "LOW_DEVICE_INPUT_VOLTAGE",
477
+ LOW_GPS_COVERAGE: "LOW_GPS_COVERAGE",
478
+ NO_CAN_DATA_CONFIGURATION: "NO_CAN_DATA_CONFIGURATION",
479
+ OPERATING_HOURS: "OPERATING_HOURS",
480
+ };
451
481
  const servicePlanStatus = {
452
482
  COMPLETE: "COMPLETE",
453
483
  DRAFT: "DRAFT",
@@ -461,6 +491,124 @@ const servicePlanStatus = {
461
491
  UNKNOWN: "UNKNOWN",
462
492
  UPCOMING: "UPCOMING",
463
493
  };
494
+ const DeviceHealthIssueCategorySummariesDocument = {
495
+ kind: "Document",
496
+ definitions: [
497
+ {
498
+ kind: "OperationDefinition",
499
+ operation: "query",
500
+ name: { kind: "Name", value: "DeviceHealthIssueCategorySummaries" },
501
+ variableDefinitions: [
502
+ {
503
+ kind: "VariableDefinition",
504
+ variable: { kind: "Variable", name: { kind: "Name", value: "filters" } },
505
+ type: { kind: "NamedType", name: { kind: "Name", value: "AssetFiltersInput" } },
506
+ },
507
+ ],
508
+ selectionSet: {
509
+ kind: "SelectionSet",
510
+ selections: [
511
+ {
512
+ kind: "Field",
513
+ name: { kind: "Name", value: "assetSummary" },
514
+ arguments: [
515
+ {
516
+ kind: "Argument",
517
+ name: { kind: "Name", value: "filters" },
518
+ value: { kind: "Variable", name: { kind: "Name", value: "filters" } },
519
+ },
520
+ ],
521
+ selectionSet: {
522
+ kind: "SelectionSet",
523
+ selections: [
524
+ {
525
+ kind: "Field",
526
+ name: { kind: "Name", value: "fleetHealthCategoriesSummary" },
527
+ selectionSet: {
528
+ kind: "SelectionSet",
529
+ selections: [
530
+ {
531
+ kind: "Field",
532
+ name: { kind: "Name", value: "summary" },
533
+ selectionSet: {
534
+ kind: "SelectionSet",
535
+ selections: [
536
+ { kind: "Field", name: { kind: "Name", value: "count" } },
537
+ { kind: "Field", name: { kind: "Name", value: "key" } },
538
+ ],
539
+ },
540
+ },
541
+ { kind: "Field", name: { kind: "Name", value: "total" } },
542
+ ],
543
+ },
544
+ },
545
+ ],
546
+ },
547
+ },
548
+ ],
549
+ },
550
+ },
551
+ ],
552
+ };
553
+ const DeviceHealthIssueTypeSummariesDocument = {
554
+ kind: "Document",
555
+ definitions: [
556
+ {
557
+ kind: "OperationDefinition",
558
+ operation: "query",
559
+ name: { kind: "Name", value: "DeviceHealthIssueTypeSummaries" },
560
+ variableDefinitions: [
561
+ {
562
+ kind: "VariableDefinition",
563
+ variable: { kind: "Variable", name: { kind: "Name", value: "filters" } },
564
+ type: { kind: "NamedType", name: { kind: "Name", value: "AssetFiltersInput" } },
565
+ },
566
+ ],
567
+ selectionSet: {
568
+ kind: "SelectionSet",
569
+ selections: [
570
+ {
571
+ kind: "Field",
572
+ name: { kind: "Name", value: "assetSummary" },
573
+ arguments: [
574
+ {
575
+ kind: "Argument",
576
+ name: { kind: "Name", value: "filters" },
577
+ value: { kind: "Variable", name: { kind: "Name", value: "filters" } },
578
+ },
579
+ ],
580
+ selectionSet: {
581
+ kind: "SelectionSet",
582
+ selections: [
583
+ {
584
+ kind: "Field",
585
+ name: { kind: "Name", value: "fleetHealthTypesSummary" },
586
+ selectionSet: {
587
+ kind: "SelectionSet",
588
+ selections: [
589
+ {
590
+ kind: "Field",
591
+ name: { kind: "Name", value: "summary" },
592
+ selectionSet: {
593
+ kind: "SelectionSet",
594
+ selections: [
595
+ { kind: "Field", name: { kind: "Name", value: "key" } },
596
+ { kind: "Field", name: { kind: "Name", value: "count" } },
597
+ ],
598
+ },
599
+ },
600
+ { kind: "Field", name: { kind: "Name", value: "total" } },
601
+ ],
602
+ },
603
+ },
604
+ ],
605
+ },
606
+ },
607
+ ],
608
+ },
609
+ },
610
+ ],
611
+ };
464
612
  const GetFleetAssetTypesSummaryDocument = {
465
613
  kind: "Document",
466
614
  definitions: [
@@ -2328,28 +2476,35 @@ const useActivityFilter = () => {
2328
2476
  };
2329
2477
 
2330
2478
  /**
2331
- * A button to clear recent searches.
2479
+ * Renders the AreaView component, which manages the UI and logic for an area filter.
2332
2480
  *
2333
- * @param {ClearItemButtonProps} props - The props for the ClearItemButton component
2334
- * @returns {ReactElement} ClearItemButton component
2481
+ * @param {FilterViewProps<AreaFilterGeoJsonGeometry>} props - The props for the component.
2482
+ * @returns {ReactElement} The rendered AreaView component.
2335
2483
  */
2336
- const ClearItemButton = ({ onClick }) => {
2484
+ const AreaView = (props) => {
2337
2485
  const [t] = useTranslation();
2338
- return (jsxRuntime.jsx(reactComponents.Tooltip, { label: t("filters.shared.clear"), children: jsxRuntime.jsx(reactComponents.IconButton, { className: "rounded-full", icon: jsxRuntime.jsx(reactComponents.Icon, { name: "Trash", size: "small" }), onClick: onClick, size: "small", variant: "ghost-neutral" }) }));
2486
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(filtersFilterBar.FilterHeader, { ...props.filterDefinition, ...props.filterBarActions, filterHasChanges: props.filterBarActions.appliedFilterKeys().includes(props.filterDefinition.filterKey) }), jsxRuntime.jsx(reactFilterComponents.FilterBody, { limitSize: true, children: jsxRuntime.jsx("p", { className: "p-2", children: `${t("assetFilters.boundingBoxFilter.value")}` }) })] }));
2339
2487
  };
2340
-
2341
2488
  /**
2342
- * A footer component that displays a count of recent searches and a clear all button.
2489
+ * Area filter definition
2343
2490
  *
2344
- * @param {RecentSearchesFooterProps} props - The props for the ClearAllFooter component
2345
- * @returns {ReactElement} RecentSearchesFooter component
2491
+ * @returns {AreaFilterDefinition} Area filter definition
2346
2492
  */
2347
- const RecentSearchesFooter = ({ count, onClearAll }) => {
2493
+ const useAreaFilter = () => {
2348
2494
  const [t] = useTranslation();
2349
- if (count === 0) {
2350
- return null;
2351
- }
2352
- return (jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-x-2 border-t-2 border-neutral-300 px-2 py-0.5", children: [jsxRuntime.jsx(reactComponents.Text, { className: "py-0.5", size: "small", subtle: true, children: t("filters.shared.recentSearches") }), count > 1 ? (jsxRuntime.jsx(reactComponents.Button, { onClick: onClearAll, size: "small", variant: "ghost", children: t("filters.shared.clearAll") })) : null] }));
2495
+ const result = react.useMemo(() => {
2496
+ return {
2497
+ filterKey: "area",
2498
+ type: "area",
2499
+ group: "CURRENT_LOCATION",
2500
+ title: t("assetFilters.area.label"),
2501
+ valueAsText: value => {
2502
+ return t("assetFilters.boundingBoxFilter.value");
2503
+ },
2504
+ component: props => jsxRuntime.jsx(AreaView, { ...props }),
2505
+ };
2506
+ }, [t]);
2507
+ return result;
2353
2508
  };
2354
2509
 
2355
2510
  const areaFilterInternalGeoJsonGeometrySchema = zod.z.union([
@@ -2531,145 +2686,6 @@ const usePlacesSearch = ({ localStorageKey = SHARED_LOCATIONS_LOCAL_STORAGE_KEY,
2531
2686
  ]);
2532
2687
  };
2533
2688
 
2534
- /**
2535
- * Renders the AreaView component, which manages the UI and logic for an area filter
2536
- * with optional search functionality.
2537
- *
2538
- * @param {FilterViewProps<AreaFilterGeoJsonGeometry> & { showWithSearch: boolean }} props - The props for the component.
2539
- * @returns {ReactElement} The rendered AreaView component.
2540
- */
2541
- const AreaView = (props) => {
2542
- const [t] = useTranslation();
2543
- const { logEvent } = reactCoreHooks.useAnalytics(filtersFilterBar.FilterEvents);
2544
- const { places, recentPlaces, setRecentPlaces, selectedPlaceData, setSelectedPrediction, searchString, setSearchString, debouncedSearchString, loading, hint, } = usePlacesSearch({
2545
- localStorageKey: "shared-recent-locations",
2546
- });
2547
- const placeholderOption = react.useMemo(() => {
2548
- // If no selected option, use this placeholder option
2549
- // Aka if applied from outside the filter UI
2550
- if (!props.value) {
2551
- return null;
2552
- }
2553
- const placeholderBbox = geoJsonUtils.getBboxFromGeoJsonPolygon(props.value);
2554
- return placeholderBbox
2555
- ? {
2556
- bBox: placeholderBbox,
2557
- geometry: props.value,
2558
- properties: { formattedAddress: t("assetFilters.area.origin.mapArea") },
2559
- dateIsoString: undefined,
2560
- placeId: "applied-map-area",
2561
- description: t("assetFilters.area.origin.mapArea"),
2562
- }
2563
- : null;
2564
- }, [props.value, t]);
2565
- const selectedOption = react.useMemo(() => getSelectedOption(props.value, recentPlaces), [props.value, recentPlaces]);
2566
- const setFilter = react.useCallback((place) => {
2567
- const { properties, bBox, geometry, dateIsoString } = place;
2568
- if (geometry.type === "Polygon") {
2569
- // Polygons are stored directly
2570
- props.filterBarActions.setArea(geometry);
2571
- }
2572
- else {
2573
- // All other geometries are stored by the filter as a
2574
- // polygon derived from the features bbox
2575
- props.filterBarActions.setArea(geoJsonUtils.getPolygonFromBbox(bBox));
2576
- }
2577
- logEvent("Filters Applied - V2", {
2578
- type: "AreaFilter",
2579
- value: properties.formattedAddress,
2580
- additionalProperties: {
2581
- geometryType: geometry.type,
2582
- wasPreviousSearch: Boolean(dateIsoString),
2583
- },
2584
- });
2585
- }, [props.filterBarActions, logEvent]);
2586
- react.useEffect(() => {
2587
- if (!selectedPlaceData) {
2588
- return;
2589
- }
2590
- if (selectedPlaceData.placeId === selectedOption?.placeId) {
2591
- return;
2592
- }
2593
- setFilter(selectedPlaceData);
2594
- }, [selectedPlaceData, setFilter, selectedOption]);
2595
- if (!props.showWithSearch) {
2596
- // Temporary while we are testing the new area filter bar behind feature flag
2597
- // This emulated the old look of the boundingbox filter
2598
- // TODO [BUSS] Remove this once the new area filter is ready for prime time
2599
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(filtersFilterBar.FilterHeader, { ...props.filterDefinition, ...props.filterBarActions, filterHasChanges: props.filterBarActions.appliedFilterKeys().includes(props.filterDefinition.filterKey) }), jsxRuntime.jsx(reactFilterComponents.FilterBody, { limitSize: true, children: jsxRuntime.jsx("p", { className: "p-2", children: `${t("assetFilters.boundingBoxFilter.value")}` }) })] }));
2600
- }
2601
- return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(filtersFilterBar.FilterHeader, { ...props.filterDefinition, ...props.filterBarActions, filterHasChanges: props.filterBarActions.appliedFilterKeys().includes(props.filterDefinition.filterKey), loading: loading, searchEnabled: true, searchProps: {
2602
- onChange: setSearchString,
2603
- onClear: () => setSearchString(""),
2604
- value: searchString,
2605
- count: places.length,
2606
- placeholder: t("assetFilters.area.searchPlaceholder"),
2607
- } }), jsxRuntime.jsx(reactFilterComponents.FilterBody, { limitSize: true, children: places.length > 0 || placeholderOption ? (jsxRuntime.jsx(filtersFilterBar.FilterResults, { loading: false, results: [
2608
- // Show placeholder option first if selected option is not in filterResult
2609
- // Aka if applied from outside the filter UI
2610
- ...(placeholderOption && !selectedOption && !debouncedSearchString ? [placeholderOption] : []),
2611
- ...places,
2612
- ], children: filterResult => (jsxRuntime.jsx(reactFormComponents.RadioGroup, { className: "m-1", id: "areaFilter", onChange: e => {
2613
- const findOption = filterResult.find(result => result.description === e.currentTarget.value);
2614
- findOption &&
2615
- setSelectedPrediction({
2616
- placeId: findOption.placeId,
2617
- description: findOption.description,
2618
- });
2619
- setSearchString(""); // Clear search input after selection
2620
- }, value: selectedOption?.description ??
2621
- placeholderOption?.description ?? // placeholder if no selected option
2622
- "", children: filterResult.map(({ ...rest }, index) => {
2623
- const selected = selectedOption?.description === rest.description;
2624
- return (jsxRuntime.jsx(reactFilterComponents.RadioFilterItem, { label: rest.description, selected: selected, suffix:
2625
- // Only show clear button if not currently selected and previously searched
2626
- !selected && "dateIsoString" in rest ? (jsxRuntime.jsx(ClearItemButton, { onClick: () => setRecentPlaces(prev => prev.filter(r => r.description !== rest.description)) })) : null, value: rest.description }, index));
2627
- }) })) })) : (jsxRuntime.jsx("p", { className: "py-2 text-center text-sm text-neutral-400", children: hint })) }), debouncedSearchString.length === 0 ? (jsxRuntime.jsx(RecentSearchesFooter, { count: recentPlaces.length, onClearAll: () => setRecentPlaces([]) })) : null] }));
2628
- };
2629
- /**
2630
- * Area filter definition
2631
- *
2632
- * @returns {AreaFilterDefinition} Area filter definition
2633
- */
2634
- const useAreaFilter = ({ showWithSearch } = {
2635
- showWithSearch: () => true,
2636
- }) => {
2637
- const [t] = useTranslation();
2638
- const { recentPlaces } = usePlacesSearch({
2639
- localStorageKey: "shared-recent-locations",
2640
- });
2641
- const result = react.useMemo(() => {
2642
- return {
2643
- filterKey: "area",
2644
- type: "area",
2645
- group: "CURRENT_LOCATION",
2646
- title: t("assetFilters.area.label"),
2647
- showInFilterBar: () => showWithSearch(),
2648
- valueAsText: value => {
2649
- // Match the applied area filter to the places option if it exists in the recent places
2650
- const nameOfSelectedArea = getSelectedOption(value, recentPlaces);
2651
- return showWithSearch()
2652
- ? (nameOfSelectedArea?.description ?? t("assetFilters.area.active"))
2653
- : t("assetFilters.boundingBoxFilter.value");
2654
- },
2655
- component: props => jsxRuntime.jsx(AreaView, { ...props, showWithSearch: showWithSearch() }),
2656
- };
2657
- }, [t, showWithSearch, recentPlaces]);
2658
- return result;
2659
- };
2660
- const getSelectedOption = (value, options) => {
2661
- return options.find(option => {
2662
- // Polygons are compared by their coordinates directly
2663
- if (option.geometry.type === "Polygon" || option.geometry.type === "MultiPolygon") {
2664
- return JSON.stringify(option.geometry.coordinates) === JSON.stringify(value?.coordinates);
2665
- }
2666
- // All other geometries are stored by the filter as a
2667
- // polygon derived from the features bbox
2668
- // therefore we need to compare by that here to reverse the conversion
2669
- return JSON.stringify(geoJsonUtils.getPolygonFromBbox(option.bBox).coordinates) === JSON.stringify(value?.coordinates);
2670
- });
2671
- };
2672
-
2673
2689
  /**
2674
2690
  * Renders a filter view component with a header and optional additional elements for Asset IDs.
2675
2691
  *
@@ -3074,6 +3090,205 @@ const useCustomerIdsFilter = ({ showInFilterBar, defaultValue, hasCount, persist
3074
3090
  return result;
3075
3091
  };
3076
3092
 
3093
+ /**
3094
+ * Get the Fleet Data Health Issue Category enum value with fallback
3095
+ *
3096
+ * @param key - The key to get the enum value for
3097
+ * @returns {FleetDataHealthIssueCategory | null} The Fleet Data Health Issue Category enum value or null if not found
3098
+ */
3099
+ const getHealthCategoryEnumWithFallback = (key) => {
3100
+ try {
3101
+ return sharedUtils.enumFromValue(key, fleetDataHealthIssueCategory);
3102
+ }
3103
+ catch {
3104
+ return null;
3105
+ }
3106
+ };
3107
+
3108
+ /**
3109
+ * Get a record of device health category display names
3110
+ *
3111
+ * @returns {Record<FleetDataHealthIssueCategory, string>} A record of device health category display names
3112
+ */
3113
+ const useDeviceHealthIssueCategoryDisplayNames = () => {
3114
+ const [t] = useTranslation();
3115
+ return react.useMemo(() => ({
3116
+ [fleetDataHealthIssueCategory.COVERAGE_ISSUES]: t("assetFilters.deviceHealthIssueCategory.coverageIssues"),
3117
+ [fleetDataHealthIssueCategory.DEVICE_BATTERY_ISSUES]: t("assetFilters.deviceHealthIssueCategory.deviceBatteryIssues"),
3118
+ [fleetDataHealthIssueCategory.INSTALL_AND_CONFIGURATION_HEALTH]: t("assetFilters.deviceHealthIssueCategory.installAndConfigurationHealth"),
3119
+ [fleetDataHealthIssueCategory.NON_REPORTING_UNIT]: t("assetFilters.deviceHealthIssueCategory.nonReportingUnit"),
3120
+ }), [t]);
3121
+ };
3122
+
3123
+ /**
3124
+ * Device Health Issue Category Filter component
3125
+ *
3126
+ * @param {FilterViewProps<Array<ValueName>>} props - Filter view props
3127
+ * @returns {ReactElement} React element
3128
+ */
3129
+ const DeviceHealthIssueCategoryFilter = (props) => {
3130
+ const categoryDisplayNames = useDeviceHealthIssueCategoryDisplayNames();
3131
+ const filters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
3132
+ const { data, loading } = reactGraphqlHooks.useQuery(DeviceHealthIssueCategorySummariesDocument, {
3133
+ variables: {
3134
+ filters: {
3135
+ ...filters,
3136
+ activeFilter: true,
3137
+ fleetHealthCategories: undefined,
3138
+ fleetHealthStates: ["OPEN"],
3139
+ },
3140
+ },
3141
+ });
3142
+ const categories = react.useMemo(() => data?.assetSummary?.fleetHealthCategoriesSummary.summary.reduce((acc, category) => {
3143
+ const existingCategory = acc.find(c => c.key === category.key);
3144
+ if (existingCategory) {
3145
+ existingCategory.count += category.count;
3146
+ }
3147
+ else {
3148
+ acc.push(category);
3149
+ }
3150
+ return acc;
3151
+ }, []), [data?.assetSummary?.fleetHealthCategoriesSummary.summary]);
3152
+ const options = react.useMemo(() => {
3153
+ return (categories
3154
+ ?.map(issueCategory => {
3155
+ const categoryKey = issueCategory.key;
3156
+ const categoryEnum = getHealthCategoryEnumWithFallback(categoryKey);
3157
+ if (!categoryEnum) {
3158
+ return null;
3159
+ }
3160
+ return {
3161
+ key: categoryKey,
3162
+ label: categoryDisplayNames[categoryEnum],
3163
+ count: issueCategory.count,
3164
+ };
3165
+ })
3166
+ .filter(sharedUtils.nonNullable) ?? []);
3167
+ }, [categories, categoryDisplayNames]);
3168
+ return jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, loading: loading, options: options });
3169
+ };
3170
+
3171
+ /**
3172
+ * Get the Device Health Issue Category filter definition
3173
+ *
3174
+ * @returns {ValueNameArrayFilterDefinition} The Device Health Issue Category filter definition
3175
+ */
3176
+ const useDeviceHealthIssueCategoryFilter = () => {
3177
+ const [t] = useTranslation();
3178
+ return react.useMemo(() => {
3179
+ return {
3180
+ filterKey: "fleetHealthCategories",
3181
+ type: "valueNameArray",
3182
+ group: "DEVICE_HEALTH",
3183
+ title: t("assetFilters.deviceHealthIssueCategories"),
3184
+ component: props => jsxRuntime.jsx(DeviceHealthIssueCategoryFilter, { ...props }),
3185
+ };
3186
+ }, [t]);
3187
+ };
3188
+
3189
+ /**
3190
+ * Get the Fleet Data Health Issue Type enum value with fallback
3191
+ *
3192
+ * @param {string} key - The key to get the enum value for
3193
+ * @returns {FleetDataHealthIssueType | null} The Fleet Data Health Issue Type enum value or null if not found
3194
+ */
3195
+ const getHealthTypeEnumWithFallback = (key) => {
3196
+ try {
3197
+ return sharedUtils.enumFromValue(key, fleetDataHealthIssueType);
3198
+ }
3199
+ catch {
3200
+ return null;
3201
+ }
3202
+ };
3203
+
3204
+ /**
3205
+ * Get a record of device health issue type display names
3206
+ *
3207
+ * @returns {Record<FleetDataHealthIssueType, string>} A record of device health issue type display names
3208
+ */
3209
+ const useDeviceHealthIssueTypeDisplayNames = () => {
3210
+ const [t] = useTranslation();
3211
+ return react.useMemo(() => ({
3212
+ [fleetDataHealthIssueType.DATA_NOT_RECEIVED]: t("assetFilters.deviceHealthIssueType.dataNotReceived"),
3213
+ [fleetDataHealthIssueType.INSTALLATION_VALIDATION_MISSING]: t("assetFilters.deviceHealthIssueType.installationValidationMissing"),
3214
+ [fleetDataHealthIssueType.LOW_CELLULAR_COVERAGE]: t("assetFilters.deviceHealthIssueType.lowCellularCoverage"),
3215
+ [fleetDataHealthIssueType.LOW_DEVICE_BATTERY_VOLTAGE]: t("assetFilters.deviceHealthIssueType.lowDeviceBatteryVoltage"),
3216
+ [fleetDataHealthIssueType.LOW_DEVICE_INPUT_VOLTAGE]: t("assetFilters.deviceHealthIssueType.lowDeviceInputVoltage"),
3217
+ [fleetDataHealthIssueType.LOW_GPS_COVERAGE]: t("assetFilters.deviceHealthIssueType.lowGpsCoverage"),
3218
+ [fleetDataHealthIssueType.NO_CAN_DATA_CONFIGURATION]: t("assetFilters.deviceHealthIssueType.noCanDataConfiguration"),
3219
+ [fleetDataHealthIssueType.OPERATING_HOURS]: t("assetFilters.deviceHealthIssueType.operatingHours"),
3220
+ }), [t]);
3221
+ };
3222
+
3223
+ /**
3224
+ * Device Health Issue Type Filter component
3225
+ *
3226
+ * @param {FilterViewProps<Array<ValueName>>} props - Filter view props
3227
+ * @returns {ReactElement} React element
3228
+ */
3229
+ const DeviceHealthIssueTypeFilter = (props) => {
3230
+ const issueTypeDisplayNames = useDeviceHealthIssueTypeDisplayNames();
3231
+ const filters = filtersGraphqlHook.useActiveAssetFilters(props.filterState.values);
3232
+ const [searchQuery, setSearchQuery] = react.useState("");
3233
+ const debouncedSearchQuery = reactComponents.useDebounce(searchQuery.trim().toLocaleLowerCase(), { delay: 300 });
3234
+ const { data, loading } = reactGraphqlHooks.useQuery(DeviceHealthIssueTypeSummariesDocument, {
3235
+ variables: {
3236
+ filters: {
3237
+ ...filters,
3238
+ activeFilter: true,
3239
+ fleetHealthTypes: undefined,
3240
+ fleetHealthStates: ["OPEN"],
3241
+ },
3242
+ },
3243
+ });
3244
+ const types = react.useMemo(() => data?.assetSummary?.fleetHealthTypesSummary.summary.reduce((acc, type) => {
3245
+ const existingType = acc.find(c => c.key === type.key);
3246
+ if (existingType) {
3247
+ existingType.count += type.count;
3248
+ }
3249
+ else {
3250
+ acc.push(type);
3251
+ }
3252
+ return acc;
3253
+ }, []), [data?.assetSummary?.fleetHealthTypesSummary.summary]);
3254
+ const options = react.useMemo(() => {
3255
+ return (types
3256
+ ?.map(issuetype => {
3257
+ const typeKey = issuetype.key;
3258
+ const typeEnum = getHealthTypeEnumWithFallback(typeKey);
3259
+ if (!typeEnum) {
3260
+ return null;
3261
+ }
3262
+ return {
3263
+ key: typeKey,
3264
+ label: issueTypeDisplayNames[typeEnum],
3265
+ count: issuetype.count,
3266
+ };
3267
+ })
3268
+ .filter(sharedUtils.nonNullable)
3269
+ .filter(option => option.label.toLowerCase().includes(debouncedSearchQuery)) ?? []);
3270
+ }, [debouncedSearchQuery, issueTypeDisplayNames, types]);
3271
+ return (jsxRuntime.jsx(filtersFilterBar.DefaultCheckboxFilter, { ...props, customSearch: { value: searchQuery, onChange: setSearchQuery }, loading: loading, options: options }));
3272
+ };
3273
+
3274
+ /**
3275
+ * Get the Device Health Issue Type filter definition
3276
+ *
3277
+ * @returns {ValueNameArrayFilterDefinition} The Device Health Issue Type filter definition
3278
+ */
3279
+ const useDeviceHealthIssueTypeFilter = () => {
3280
+ const [t] = useTranslation();
3281
+ return react.useMemo(() => {
3282
+ return {
3283
+ filterKey: "fleetHealthTypes",
3284
+ type: "valueNameArray",
3285
+ group: "DEVICE_HEALTH",
3286
+ title: t("assetFilters.deviceHealthIssueTypes"),
3287
+ component: props => jsxRuntime.jsx(DeviceHealthIssueTypeFilter, { ...props }),
3288
+ };
3289
+ }, [t]);
3290
+ };
3291
+
3077
3292
  /**
3078
3293
  * The `FollowedFiltersView` component displays filter settings for "Followed" and allows the user to select between different values.
3079
3294
  *
@@ -3692,6 +3907,31 @@ const useRentalContractOrderNumberFilter = ({ showInFilterBar } = {
3692
3907
  return result;
3693
3908
  };
3694
3909
 
3910
+ /**
3911
+ * A button to clear recent searches.
3912
+ *
3913
+ * @param {ClearItemButtonProps} props - The props for the ClearItemButton component
3914
+ * @returns {ReactElement} ClearItemButton component
3915
+ */
3916
+ const ClearItemButton = ({ onClick }) => {
3917
+ const [t] = useTranslation();
3918
+ return (jsxRuntime.jsx(reactComponents.Tooltip, { label: t("filters.shared.clear"), children: jsxRuntime.jsx(reactComponents.IconButton, { className: "rounded-full", icon: jsxRuntime.jsx(reactComponents.Icon, { name: "Trash", size: "small" }), onClick: onClick, size: "small", variant: "ghost-neutral" }) }));
3919
+ };
3920
+
3921
+ /**
3922
+ * A footer component that displays a count of recent searches and a clear all button.
3923
+ *
3924
+ * @param {RecentSearchesFooterProps} props - The props for the ClearAllFooter component
3925
+ * @returns {ReactElement} RecentSearchesFooter component
3926
+ */
3927
+ const RecentSearchesFooter = ({ count, onClearAll }) => {
3928
+ const [t] = useTranslation();
3929
+ if (count === 0) {
3930
+ return null;
3931
+ }
3932
+ return (jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-x-2 border-t-2 border-neutral-300 px-2 py-0.5", children: [jsxRuntime.jsx(reactComponents.Text, { className: "py-0.5", size: "small", subtle: true, children: t("filters.shared.recentSearches") }), count > 1 ? (jsxRuntime.jsx(reactComponents.Button, { onClick: onClearAll, size: "small", variant: "ghost", children: t("filters.shared.clearAll") })) : null] }));
3933
+ };
3934
+
3695
3935
  const MAX_RECENT_SEARCHES$1 = 20;
3696
3936
  /**
3697
3937
  * Rental contract reference code description filter view component.
@@ -4458,6 +4698,44 @@ const useTypesFilter = () => {
4458
4698
  return result;
4459
4699
  };
4460
4700
 
4701
+ const mockForDeviceHealthIssueCategorySummariesQuery = (variables, data) => {
4702
+ return reactCoreContextsTest.queryFor(DeviceHealthIssueCategorySummariesDocument, variables, utilities.mergeDeep({
4703
+ __typename: "Query",
4704
+ assetSummary: {
4705
+ __typename: "AssetSummary",
4706
+ fleetHealthCategoriesSummary: {
4707
+ __typename: "MetadataSummary",
4708
+ total: 6273236744536064,
4709
+ summary: [
4710
+ {
4711
+ __typename: "Summary",
4712
+ count: 6273236744536064,
4713
+ key: "subito",
4714
+ },
4715
+ ],
4716
+ },
4717
+ },
4718
+ }, data || {}));
4719
+ };
4720
+ const mockForDeviceHealthIssueTypeSummariesQuery = (variables, data) => {
4721
+ return reactCoreContextsTest.queryFor(DeviceHealthIssueTypeSummariesDocument, variables, utilities.mergeDeep({
4722
+ __typename: "Query",
4723
+ assetSummary: {
4724
+ __typename: "AssetSummary",
4725
+ fleetHealthTypesSummary: {
4726
+ __typename: "MetadataSummary",
4727
+ total: 6273236744536064,
4728
+ summary: [
4729
+ {
4730
+ __typename: "Summary",
4731
+ key: "subito",
4732
+ count: 6273236744536064,
4733
+ },
4734
+ ],
4735
+ },
4736
+ },
4737
+ }, data || {}));
4738
+ };
4461
4739
  const mockForGetFleetAssetTypesSummaryQuery = (variables, data) => {
4462
4740
  return reactCoreContextsTest.queryFor(GetFleetAssetTypesSummaryDocument, variables, utilities.mergeDeep({
4463
4741
  __typename: "Query",
@@ -4951,7 +5229,7 @@ const mockForGetAccessManagementModeDesiredSummaryQuery = (variables, data) => {
4951
5229
  *
4952
5230
  * @returns {FilterBarDefinition} Default asset filter bar definition
4953
5231
  */
4954
- const useDefaultAssetFilterBarDefinition = ({ sitesEnabled, owningDepotEnabled, serviceManagementEnabled, areaShowWithSearch, ownerFilterDefaultValue, showHiddenAssetsEnabled, }) => {
5232
+ const useDefaultAssetFilterBarDefinition = ({ sitesEnabled, owningDepotEnabled, serviceManagementEnabled, ownerFilterDefaultValue, showHiddenAssetsEnabled, }) => {
4955
5233
  const assetType = useAssetTypeFilter();
4956
5234
  const metadataCompleteness = useMetadataCompletenessFilter();
4957
5235
  const groups = useGroupIdsFilter();
@@ -4983,12 +5261,7 @@ const useDefaultAssetFilterBarDefinition = ({ sitesEnabled, owningDepotEnabled,
4983
5261
  const ownerAccountIds = useOwnerAccountIdsFilter(ownerFilterDefaultValue);
4984
5262
  const searchProps = react.useMemo(() => ({ localStorageKey: "assetSearch" }), []);
4985
5263
  const search = useSearchFilter(searchProps);
4986
- const areaEnabledProps = react.useMemo(() => {
4987
- return {
4988
- showWithSearch: () => areaShowWithSearch ?? false,
4989
- };
4990
- }, [areaShowWithSearch]);
4991
- const area = useAreaFilter(areaEnabledProps);
5264
+ const area = useAreaFilter();
4992
5265
  const productionYears = useProductionYearFilter();
4993
5266
  const partner = usePartnerFilter();
4994
5267
  const serviceManagementEnabledProps = react.useMemo(() => {
@@ -5005,6 +5278,8 @@ const useDefaultAssetFilterBarDefinition = ({ sitesEnabled, owningDepotEnabled,
5005
5278
  }, [showHiddenAssetsEnabled]);
5006
5279
  const activeFilter = useActiveFilterFilter(activeFilterEnabledProps);
5007
5280
  const accessManagementMode = useAccessManagementModeFilter();
5281
+ const fleetHealthTypes = useDeviceHealthIssueTypeFilter();
5282
+ const fleetHealthCategories = useDeviceHealthIssueCategoryFilter();
5008
5283
  return react.useMemo(() => {
5009
5284
  return {
5010
5285
  assetType,
@@ -5029,6 +5304,8 @@ const useDefaultAssetFilterBarDefinition = ({ sitesEnabled, owningDepotEnabled,
5029
5304
  partner,
5030
5305
  search,
5031
5306
  accessManagementMode,
5307
+ fleetHealthTypes,
5308
+ fleetHealthCategories,
5032
5309
  };
5033
5310
  }, [
5034
5311
  siteIds,
@@ -5053,6 +5330,8 @@ const useDefaultAssetFilterBarDefinition = ({ sitesEnabled, owningDepotEnabled,
5053
5330
  activeFilter,
5054
5331
  siteDepotOwnershipIds,
5055
5332
  accessManagementMode,
5333
+ fleetHealthTypes,
5334
+ fleetHealthCategories,
5056
5335
  ]);
5057
5336
  };
5058
5337
 
@@ -5105,6 +5384,8 @@ exports.mapActivityToLabelId = mapActivityToLabelId;
5105
5384
  exports.mapMetadataCompletenessToLabelId = mapMetadataCompletenessToLabelId;
5106
5385
  exports.metadataCompleteness = metadataCompleteness;
5107
5386
  exports.metadataCompletenessOptions = metadataCompletenessOptions;
5387
+ exports.mockForDeviceHealthIssueCategorySummariesQuery = mockForDeviceHealthIssueCategorySummariesQuery;
5388
+ exports.mockForDeviceHealthIssueTypeSummariesQuery = mockForDeviceHealthIssueTypeSummariesQuery;
5108
5389
  exports.mockForGetAccessManagementModeDesiredSummaryQuery = mockForGetAccessManagementModeDesiredSummaryQuery;
5109
5390
  exports.mockForGetAssetTelematicsDeviceConnectionSummaryQuery = mockForGetAssetTelematicsDeviceConnectionSummaryQuery;
5110
5391
  exports.mockForGetCustomFieldSummaryQuery = mockForGetCustomFieldSummaryQuery;
@@ -5143,6 +5424,8 @@ exports.useBrandFilter = useBrandFilter;
5143
5424
  exports.useCriticalityFilter = useCriticalityFilter;
5144
5425
  exports.useCustomerIdsFilter = useCustomerIdsFilter;
5145
5426
  exports.useDefaultAssetFilterBarDefinition = useDefaultAssetFilterBarDefinition;
5427
+ exports.useDeviceHealthIssueCategoryFilter = useDeviceHealthIssueCategoryFilter;
5428
+ exports.useDeviceHealthIssueTypeFilter = useDeviceHealthIssueTypeFilter;
5146
5429
  exports.useFollowedFilter = useFollowedFilter;
5147
5430
  exports.useGroupIdsFilter = useGroupIdsFilter;
5148
5431
  exports.useHourIntervalFilter = useHourIntervalFilter;