@adiba-banking-cloud/backoffice 0.2.0 → 0.2.3
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/build/index.cjs.js/{heatmap-c3tdleHx.js → heatmap-QyWScAOZ.js} +1 -1
- package/build/index.cjs.js/{index-QwR6crYB.js → index-BHsXwqJB.js} +253 -16
- package/build/index.cjs.js/index.js +7 -1
- package/build/index.esm.js/{heatmap-Dfb5-pNh.js → heatmap-CZ2o0bqY.js} +1 -1
- package/build/index.esm.js/{index-9HtrJaD9.js → index-BlLQ1b_6.js} +251 -18
- package/build/index.esm.js/index.js +3 -1
- package/build/typings/index.d.ts +4 -0
- package/build/typings/shared/api/types.d.ts +10 -0
- package/build/typings/shared/hocs/index.d.ts +1 -0
- package/build/typings/shared/hocs/withProviders.d.ts +49 -0
- package/build/typings/shared/hooks/index.d.ts +1 -0
- package/build/typings/shared/hooks/useUrlFilters.d.ts +88 -0
- package/build/typings/shared/types/index.d.ts +1 -0
- package/build/typings/shared/types/pagination.d.ts +16 -0
- package/build/typings/shared/utils/index.d.ts +1 -0
- package/build/typings/shared/utils/stringHelpers.d.ts +2 -0
- package/package.json +6 -2
|
@@ -22,6 +22,8 @@ require('@fontsource/poppins/800.css');
|
|
|
22
22
|
var axios = require('axios');
|
|
23
23
|
var dates = require('@mantine/dates');
|
|
24
24
|
require('@mantine/dates/styles.css');
|
|
25
|
+
var reactQuery = require('@tanstack/react-query');
|
|
26
|
+
var reactQueryDevtools = require('@tanstack/react-query-devtools');
|
|
25
27
|
|
|
26
28
|
function _interopNamespaceDefault(e) {
|
|
27
29
|
var n = Object.create(null);
|
|
@@ -12170,7 +12172,7 @@ const initChart$1 = props => {
|
|
|
12170
12172
|
}
|
|
12171
12173
|
|
|
12172
12174
|
// Fallback: use dynamic import (async, but will work in Vite/Storybook)
|
|
12173
|
-
Promise.resolve().then(function () { return require('./heatmap-
|
|
12175
|
+
Promise.resolve().then(function () { return require('./heatmap-QyWScAOZ.js'); }).then(function (n) { return n.heatmap; }).then(heatmapModule => {
|
|
12174
12176
|
const moduleFn = typeof heatmapModule === "function" ? heatmapModule : heatmapModule?.default || heatmapModule;
|
|
12175
12177
|
if (typeof moduleFn === "function") {
|
|
12176
12178
|
moduleFn(Highcharts);
|
|
@@ -13733,19 +13735,32 @@ const SimpleTable = _ref => {
|
|
|
13733
13735
|
actionFn,
|
|
13734
13736
|
isStriped
|
|
13735
13737
|
} = _ref;
|
|
13736
|
-
columns
|
|
13737
|
-
const
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13738
|
+
// Memoize the final columns array to avoid mutations on every render
|
|
13739
|
+
const finalColumns = React.useMemo(() => {
|
|
13740
|
+
// Create a new array to avoid mutating the original
|
|
13741
|
+
const sortedColumns = [...columns].sort((a, b) => a.order - b.order);
|
|
13742
|
+
const indexColumn = {
|
|
13743
|
+
order: -99,
|
|
13744
|
+
id: "index",
|
|
13745
|
+
label: "Id"
|
|
13746
|
+
};
|
|
13747
|
+
const actionColumn = {
|
|
13748
|
+
order: 99999,
|
|
13749
|
+
id: "action",
|
|
13750
|
+
label: ""
|
|
13751
|
+
};
|
|
13752
|
+
|
|
13753
|
+
// Build final array without mutations
|
|
13754
|
+
const result = [];
|
|
13755
|
+
if (withIndex) {
|
|
13756
|
+
result.push(indexColumn);
|
|
13757
|
+
}
|
|
13758
|
+
result.push(...sortedColumns);
|
|
13759
|
+
if (withAction && actionFn) {
|
|
13760
|
+
result.push(actionColumn);
|
|
13761
|
+
}
|
|
13762
|
+
return result;
|
|
13763
|
+
}, [columns, withIndex, withAction, actionFn]);
|
|
13749
13764
|
const isStripedProps = {
|
|
13750
13765
|
striped: "even",
|
|
13751
13766
|
highlightOnHover: true,
|
|
@@ -13754,7 +13769,7 @@ const SimpleTable = _ref => {
|
|
|
13754
13769
|
};
|
|
13755
13770
|
return /*#__PURE__*/React.createElement(core.Table, isStriped && isStripedProps, /*#__PURE__*/React.createElement(core.Table.Thead, null, /*#__PURE__*/React.createElement(core.Table.Tr, {
|
|
13756
13771
|
bg: isStriped ? "gray.1" : "transparent"
|
|
13757
|
-
},
|
|
13772
|
+
}, finalColumns.map((column, index) => {
|
|
13758
13773
|
return /*#__PURE__*/React.createElement(SimpleHeader, _extends({
|
|
13759
13774
|
key: `column-${index}`
|
|
13760
13775
|
}, column));
|
|
@@ -13762,7 +13777,7 @@ const SimpleTable = _ref => {
|
|
|
13762
13777
|
return /*#__PURE__*/React.createElement(SimpleBody, {
|
|
13763
13778
|
key: index,
|
|
13764
13779
|
row,
|
|
13765
|
-
columns,
|
|
13780
|
+
columns: finalColumns,
|
|
13766
13781
|
withAction,
|
|
13767
13782
|
withIndex,
|
|
13768
13783
|
actionFn,
|
|
@@ -14445,6 +14460,127 @@ const MAX_PAGE_SIZE = 100;
|
|
|
14445
14460
|
*/
|
|
14446
14461
|
const DEFAULT_API_TIMEOUT = 30000;
|
|
14447
14462
|
|
|
14463
|
+
/**
|
|
14464
|
+
* Configuration for URL filter hook
|
|
14465
|
+
*/
|
|
14466
|
+
|
|
14467
|
+
/**
|
|
14468
|
+
* Return type for useUrlFilters hook
|
|
14469
|
+
*/
|
|
14470
|
+
|
|
14471
|
+
/**
|
|
14472
|
+
* Generic hook for managing URL-based filters with pagination
|
|
14473
|
+
*
|
|
14474
|
+
* @example
|
|
14475
|
+
* ```tsx
|
|
14476
|
+
* interface MyFilters {
|
|
14477
|
+
* page: number;
|
|
14478
|
+
* limit: number;
|
|
14479
|
+
* name?: string;
|
|
14480
|
+
* status?: string;
|
|
14481
|
+
* }
|
|
14482
|
+
*
|
|
14483
|
+
* const { filters, updateFilters, clearFilters } = useUrlFilters<MyFilters>({
|
|
14484
|
+
* parseFilters: (params) => ({
|
|
14485
|
+
* page: parseInt(params.get('page') || '1', 10),
|
|
14486
|
+
* limit: parseInt(params.get('limit') || '10', 10),
|
|
14487
|
+
* name: params.get('name') || undefined,
|
|
14488
|
+
* status: params.get('status') || undefined,
|
|
14489
|
+
* }),
|
|
14490
|
+
* serializeFilters: (filters, params) => {
|
|
14491
|
+
* if (filters.page) params.set('page', String(filters.page));
|
|
14492
|
+
* if (filters.limit) params.set('limit', String(filters.limit));
|
|
14493
|
+
* if (filters.name) params.set('name', filters.name);
|
|
14494
|
+
* if (filters.status) params.set('status', filters.status);
|
|
14495
|
+
* },
|
|
14496
|
+
* });
|
|
14497
|
+
* ```
|
|
14498
|
+
*/
|
|
14499
|
+
function useUrlFilters(options) {
|
|
14500
|
+
const {
|
|
14501
|
+
defaultPageSize = DEFAULT_PAGE_SIZE,
|
|
14502
|
+
parseFilters,
|
|
14503
|
+
serializeFilters,
|
|
14504
|
+
hasActiveFilters: checkActiveFilters,
|
|
14505
|
+
toApiParams
|
|
14506
|
+
} = options;
|
|
14507
|
+
const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
|
|
14508
|
+
const filters = React.useMemo(() => {
|
|
14509
|
+
const parsed = parseFilters(searchParams);
|
|
14510
|
+
|
|
14511
|
+
// Ensure page and limit are always present with valid defaults
|
|
14512
|
+
const page = typeof parsed.page === "number" && parsed.page > 0 ? parsed.page : 1;
|
|
14513
|
+
const limit = typeof parsed.limit === "number" && parsed.limit > 0 ? parsed.limit : defaultPageSize;
|
|
14514
|
+
return {
|
|
14515
|
+
...parsed,
|
|
14516
|
+
page,
|
|
14517
|
+
limit
|
|
14518
|
+
};
|
|
14519
|
+
}, [searchParams, parseFilters, defaultPageSize]);
|
|
14520
|
+
const updateFilters = newFilters => {
|
|
14521
|
+
const params = new URLSearchParams(searchParams);
|
|
14522
|
+
|
|
14523
|
+
// Merge new filters with existing filters
|
|
14524
|
+
const mergedFilters = {
|
|
14525
|
+
...filters,
|
|
14526
|
+
...newFilters
|
|
14527
|
+
};
|
|
14528
|
+
|
|
14529
|
+
// Determine if we should reset page to 1
|
|
14530
|
+
// Reset if: page is not explicitly set AND other filters are changing
|
|
14531
|
+
const hasNonPaginationChanges = Object.keys(newFilters).some(key => key !== "page" && key !== "limit");
|
|
14532
|
+
if (newFilters.page === undefined && hasNonPaginationChanges) {
|
|
14533
|
+
mergedFilters.page = 1; // Reset to page 1
|
|
14534
|
+
}
|
|
14535
|
+
|
|
14536
|
+
// Ensure page and limit are numbers
|
|
14537
|
+
if (typeof mergedFilters.page !== "number" || mergedFilters.page < 1) {
|
|
14538
|
+
mergedFilters.page = 1;
|
|
14539
|
+
}
|
|
14540
|
+
if (typeof mergedFilters.limit !== "number" || mergedFilters.limit < 1) {
|
|
14541
|
+
mergedFilters.limit = defaultPageSize;
|
|
14542
|
+
}
|
|
14543
|
+
|
|
14544
|
+
// Serialize all filters
|
|
14545
|
+
serializeFilters(mergedFilters, params);
|
|
14546
|
+
setSearchParams(params, {
|
|
14547
|
+
replace: true
|
|
14548
|
+
});
|
|
14549
|
+
};
|
|
14550
|
+
const clearFilters = () => {
|
|
14551
|
+
const params = new URLSearchParams();
|
|
14552
|
+
params.set("page", "1");
|
|
14553
|
+
params.set("limit", String(defaultPageSize));
|
|
14554
|
+
setSearchParams(params, {
|
|
14555
|
+
replace: true
|
|
14556
|
+
});
|
|
14557
|
+
};
|
|
14558
|
+
const hasActiveFilters = React.useMemo(() => {
|
|
14559
|
+
if (checkActiveFilters) {
|
|
14560
|
+
return checkActiveFilters(filters);
|
|
14561
|
+
}
|
|
14562
|
+
// Default: check if any non-pagination fields have values
|
|
14563
|
+
return Object.keys(filters).some(key => {
|
|
14564
|
+
if (key === "page" || key === "limit") return false;
|
|
14565
|
+
const value = filters[key];
|
|
14566
|
+
return value !== undefined && value !== null && value !== "";
|
|
14567
|
+
});
|
|
14568
|
+
}, [filters, checkActiveFilters]);
|
|
14569
|
+
const apiParams = React.useMemo(() => {
|
|
14570
|
+
if (toApiParams) {
|
|
14571
|
+
return toApiParams(filters);
|
|
14572
|
+
}
|
|
14573
|
+
return undefined;
|
|
14574
|
+
}, [filters, toApiParams]);
|
|
14575
|
+
return {
|
|
14576
|
+
filters,
|
|
14577
|
+
updateFilters,
|
|
14578
|
+
clearFilters,
|
|
14579
|
+
hasActiveFilters,
|
|
14580
|
+
apiParams
|
|
14581
|
+
};
|
|
14582
|
+
}
|
|
14583
|
+
|
|
14448
14584
|
class ApiClient {
|
|
14449
14585
|
constructor(config) {
|
|
14450
14586
|
const {
|
|
@@ -14548,6 +14684,103 @@ const ModalContentWrapper = _ref => {
|
|
|
14548
14684
|
}, children));
|
|
14549
14685
|
};
|
|
14550
14686
|
|
|
14687
|
+
/**
|
|
14688
|
+
* Default QueryClient configuration
|
|
14689
|
+
*/
|
|
14690
|
+
const defaultQueryClient = new reactQuery.QueryClient({
|
|
14691
|
+
defaultOptions: {
|
|
14692
|
+
queries: {
|
|
14693
|
+
retry: 1,
|
|
14694
|
+
refetchOnWindowFocus: false,
|
|
14695
|
+
staleTime: 30000,
|
|
14696
|
+
// 30 seconds
|
|
14697
|
+
gcTime: 5 * 60 * 1000 // 5 minutes
|
|
14698
|
+
},
|
|
14699
|
+
mutations: {
|
|
14700
|
+
retry: false
|
|
14701
|
+
}
|
|
14702
|
+
}
|
|
14703
|
+
});
|
|
14704
|
+
/**
|
|
14705
|
+
* Higher-order component that wraps a component with all necessary providers:
|
|
14706
|
+
* - QueryClientProvider (React Query)
|
|
14707
|
+
* - MantineProvider (Mantine UI)
|
|
14708
|
+
* - DatesProvider (Mantine Dates)
|
|
14709
|
+
*
|
|
14710
|
+
* @param Component - Component to wrap
|
|
14711
|
+
* @param options - Optional configuration
|
|
14712
|
+
* @returns Wrapped component with all providers
|
|
14713
|
+
*
|
|
14714
|
+
* @example
|
|
14715
|
+
* ```tsx
|
|
14716
|
+
* // Using default configuration
|
|
14717
|
+
* const WrappedComponent = withProviders(MyComponent);
|
|
14718
|
+
*
|
|
14719
|
+
* // Using custom QueryClient
|
|
14720
|
+
* const customQueryClient = new QueryClient({ ... });
|
|
14721
|
+
* const WrappedComponent = withProviders(MyComponent, {
|
|
14722
|
+
* queryClient: customQueryClient,
|
|
14723
|
+
* });
|
|
14724
|
+
* ```
|
|
14725
|
+
*/
|
|
14726
|
+
function withProviders(Component) {
|
|
14727
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
14728
|
+
const {
|
|
14729
|
+
queryClient = defaultQueryClient,
|
|
14730
|
+
enableDevtools = true,
|
|
14731
|
+
theme: customTheme = theme,
|
|
14732
|
+
datesSettings = {
|
|
14733
|
+
locale: "en",
|
|
14734
|
+
timezone: "UTC"
|
|
14735
|
+
}
|
|
14736
|
+
} = options;
|
|
14737
|
+
const WrappedComponent = props => {
|
|
14738
|
+
const showDevtools = enableDevtools && typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
14739
|
+
return /*#__PURE__*/React__namespace.createElement(reactQuery.QueryClientProvider, {
|
|
14740
|
+
client: queryClient
|
|
14741
|
+
}, /*#__PURE__*/React__namespace.createElement(core.MantineProvider, {
|
|
14742
|
+
theme: customTheme
|
|
14743
|
+
}, /*#__PURE__*/React__namespace.createElement(dates.DatesProvider, {
|
|
14744
|
+
settings: datesSettings
|
|
14745
|
+
}, /*#__PURE__*/React__namespace.createElement(Component, props), showDevtools && /*#__PURE__*/React__namespace.createElement(reactQueryDevtools.ReactQueryDevtools, null))));
|
|
14746
|
+
};
|
|
14747
|
+
WrappedComponent.displayName = `withProviders(${Component.displayName || Component.name || "Component"})`;
|
|
14748
|
+
return WrappedComponent;
|
|
14749
|
+
}
|
|
14750
|
+
|
|
14751
|
+
/**
|
|
14752
|
+
* String utility functions for text manipulation
|
|
14753
|
+
*/
|
|
14754
|
+
const StringHelpers = {
|
|
14755
|
+
/**
|
|
14756
|
+
* Extracts text between curly braces from a string
|
|
14757
|
+
* @param input - Input string that may contain text in braces
|
|
14758
|
+
* @returns The text between braces, or empty string if not found
|
|
14759
|
+
* @example
|
|
14760
|
+
* extractBetweenBraces("Hello {world}") // returns "world"
|
|
14761
|
+
* extractBetweenBraces("No braces") // returns ""
|
|
14762
|
+
*/
|
|
14763
|
+
extractBetweenBraces: input => {
|
|
14764
|
+
const regex = /^[^{]*\{([^}]*)\}[^{]*$/;
|
|
14765
|
+
const match = input.match(regex);
|
|
14766
|
+
return match ? match[1] : "";
|
|
14767
|
+
},
|
|
14768
|
+
/**
|
|
14769
|
+
* Removes text within curly braces from a string
|
|
14770
|
+
* @param input - Input string that may contain text in braces
|
|
14771
|
+
* @returns The string with braces and their content removed, trimmed
|
|
14772
|
+
* @example
|
|
14773
|
+
* extractOutsideBraces("Hello {world}") // returns "Hello"
|
|
14774
|
+
* extractOutsideBraces("No braces") // returns "No braces"
|
|
14775
|
+
*/
|
|
14776
|
+
extractOutsideBraces: input => {
|
|
14777
|
+
const regex = /\{[^}]*\}/g;
|
|
14778
|
+
return input.replace(regex, "").trim();
|
|
14779
|
+
}
|
|
14780
|
+
};
|
|
14781
|
+
const extractBetweenBraces = StringHelpers.extractBetweenBraces;
|
|
14782
|
+
const extractOutsideBraces = StringHelpers.extractOutsideBraces;
|
|
14783
|
+
|
|
14551
14784
|
exports.ApplicationMenu = ApplicationMenu;
|
|
14552
14785
|
exports.ApplicationPanel = ApplicationPanel;
|
|
14553
14786
|
exports.AvatarLabelPanel = AvatarLabelPanel;
|
|
@@ -14594,7 +14827,11 @@ exports.TwoFactorModal = TwoFactorModal;
|
|
|
14594
14827
|
exports.UserMenu = UserMenu;
|
|
14595
14828
|
exports.apiClient = apiClient;
|
|
14596
14829
|
exports.createApiClient = createApiClient;
|
|
14830
|
+
exports.extractBetweenBraces = extractBetweenBraces;
|
|
14831
|
+
exports.extractOutsideBraces = extractOutsideBraces;
|
|
14597
14832
|
exports.getDefaultExportFromCjs = getDefaultExportFromCjs;
|
|
14598
14833
|
exports.theme = theme;
|
|
14599
14834
|
exports.useManagedModals = useManagedModals;
|
|
14600
14835
|
exports.useModal = useModal;
|
|
14836
|
+
exports.useUrlFilters = useUrlFilters;
|
|
14837
|
+
exports.withProviders = withProviders;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-BHsXwqJB.js');
|
|
4
4
|
require('@mantine/modals');
|
|
5
5
|
require('react');
|
|
6
6
|
require('@mantine/core');
|
|
@@ -23,6 +23,8 @@ require('@fontsource/poppins/800.css');
|
|
|
23
23
|
require('axios');
|
|
24
24
|
require('@mantine/dates');
|
|
25
25
|
require('@mantine/dates/styles.css');
|
|
26
|
+
require('@tanstack/react-query');
|
|
27
|
+
require('@tanstack/react-query-devtools');
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
|
|
@@ -72,6 +74,10 @@ exports.TwoFactorModal = index.TwoFactorModal;
|
|
|
72
74
|
exports.UserMenu = index.UserMenu;
|
|
73
75
|
exports.apiClient = index.apiClient;
|
|
74
76
|
exports.createApiClient = index.createApiClient;
|
|
77
|
+
exports.extractBetweenBraces = index.extractBetweenBraces;
|
|
78
|
+
exports.extractOutsideBraces = index.extractOutsideBraces;
|
|
75
79
|
exports.theme = index.theme;
|
|
76
80
|
exports.useManagedModals = index.useManagedModals;
|
|
77
81
|
exports.useModal = index.useModal;
|
|
82
|
+
exports.useUrlFilters = index.useUrlFilters;
|
|
83
|
+
exports.withProviders = index.withProviders;
|
|
@@ -7,7 +7,7 @@ import _extends from '@babel/runtime/helpers/extends';
|
|
|
7
7
|
import HighchartsReact from 'highcharts-react-official';
|
|
8
8
|
import HighchartsRounded from 'highcharts-rounded-corners';
|
|
9
9
|
import * as IconSax from 'iconsax-react';
|
|
10
|
-
import { Link } from 'react-router-dom';
|
|
10
|
+
import { Link, useSearchParams } from 'react-router-dom';
|
|
11
11
|
import { useDisclosure, useToggle } from '@mantine/hooks';
|
|
12
12
|
import { useForm } from '@mantine/form';
|
|
13
13
|
import '@fontsource/poppins/100.css';
|
|
@@ -21,6 +21,8 @@ import '@fontsource/poppins/800.css';
|
|
|
21
21
|
import axios from 'axios';
|
|
22
22
|
import { DatesProvider } from '@mantine/dates';
|
|
23
23
|
import '@mantine/dates/styles.css';
|
|
24
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
25
|
+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
24
26
|
|
|
25
27
|
function _mergeNamespaces(n, m) {
|
|
26
28
|
m.forEach(function (e) {
|
|
@@ -12149,7 +12151,7 @@ const initChart$1 = props => {
|
|
|
12149
12151
|
}
|
|
12150
12152
|
|
|
12151
12153
|
// Fallback: use dynamic import (async, but will work in Vite/Storybook)
|
|
12152
|
-
import('./heatmap-
|
|
12154
|
+
import('./heatmap-CZ2o0bqY.js').then(function (n) { return n.h; }).then(heatmapModule => {
|
|
12153
12155
|
const moduleFn = typeof heatmapModule === "function" ? heatmapModule : heatmapModule?.default || heatmapModule;
|
|
12154
12156
|
if (typeof moduleFn === "function") {
|
|
12155
12157
|
moduleFn(Highcharts);
|
|
@@ -13712,19 +13714,32 @@ const SimpleTable = _ref => {
|
|
|
13712
13714
|
actionFn,
|
|
13713
13715
|
isStriped
|
|
13714
13716
|
} = _ref;
|
|
13715
|
-
columns
|
|
13716
|
-
const
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13717
|
+
// Memoize the final columns array to avoid mutations on every render
|
|
13718
|
+
const finalColumns = useMemo(() => {
|
|
13719
|
+
// Create a new array to avoid mutating the original
|
|
13720
|
+
const sortedColumns = [...columns].sort((a, b) => a.order - b.order);
|
|
13721
|
+
const indexColumn = {
|
|
13722
|
+
order: -99,
|
|
13723
|
+
id: "index",
|
|
13724
|
+
label: "Id"
|
|
13725
|
+
};
|
|
13726
|
+
const actionColumn = {
|
|
13727
|
+
order: 99999,
|
|
13728
|
+
id: "action",
|
|
13729
|
+
label: ""
|
|
13730
|
+
};
|
|
13731
|
+
|
|
13732
|
+
// Build final array without mutations
|
|
13733
|
+
const result = [];
|
|
13734
|
+
if (withIndex) {
|
|
13735
|
+
result.push(indexColumn);
|
|
13736
|
+
}
|
|
13737
|
+
result.push(...sortedColumns);
|
|
13738
|
+
if (withAction && actionFn) {
|
|
13739
|
+
result.push(actionColumn);
|
|
13740
|
+
}
|
|
13741
|
+
return result;
|
|
13742
|
+
}, [columns, withIndex, withAction, actionFn]);
|
|
13728
13743
|
const isStripedProps = {
|
|
13729
13744
|
striped: "even",
|
|
13730
13745
|
highlightOnHover: true,
|
|
@@ -13733,7 +13748,7 @@ const SimpleTable = _ref => {
|
|
|
13733
13748
|
};
|
|
13734
13749
|
return /*#__PURE__*/React__default.createElement(Table, isStriped && isStripedProps, /*#__PURE__*/React__default.createElement(Table.Thead, null, /*#__PURE__*/React__default.createElement(Table.Tr, {
|
|
13735
13750
|
bg: isStriped ? "gray.1" : "transparent"
|
|
13736
|
-
},
|
|
13751
|
+
}, finalColumns.map((column, index) => {
|
|
13737
13752
|
return /*#__PURE__*/React__default.createElement(SimpleHeader, _extends({
|
|
13738
13753
|
key: `column-${index}`
|
|
13739
13754
|
}, column));
|
|
@@ -13741,7 +13756,7 @@ const SimpleTable = _ref => {
|
|
|
13741
13756
|
return /*#__PURE__*/React__default.createElement(SimpleBody, {
|
|
13742
13757
|
key: index,
|
|
13743
13758
|
row,
|
|
13744
|
-
columns,
|
|
13759
|
+
columns: finalColumns,
|
|
13745
13760
|
withAction,
|
|
13746
13761
|
withIndex,
|
|
13747
13762
|
actionFn,
|
|
@@ -14424,6 +14439,127 @@ const MAX_PAGE_SIZE = 100;
|
|
|
14424
14439
|
*/
|
|
14425
14440
|
const DEFAULT_API_TIMEOUT = 30000;
|
|
14426
14441
|
|
|
14442
|
+
/**
|
|
14443
|
+
* Configuration for URL filter hook
|
|
14444
|
+
*/
|
|
14445
|
+
|
|
14446
|
+
/**
|
|
14447
|
+
* Return type for useUrlFilters hook
|
|
14448
|
+
*/
|
|
14449
|
+
|
|
14450
|
+
/**
|
|
14451
|
+
* Generic hook for managing URL-based filters with pagination
|
|
14452
|
+
*
|
|
14453
|
+
* @example
|
|
14454
|
+
* ```tsx
|
|
14455
|
+
* interface MyFilters {
|
|
14456
|
+
* page: number;
|
|
14457
|
+
* limit: number;
|
|
14458
|
+
* name?: string;
|
|
14459
|
+
* status?: string;
|
|
14460
|
+
* }
|
|
14461
|
+
*
|
|
14462
|
+
* const { filters, updateFilters, clearFilters } = useUrlFilters<MyFilters>({
|
|
14463
|
+
* parseFilters: (params) => ({
|
|
14464
|
+
* page: parseInt(params.get('page') || '1', 10),
|
|
14465
|
+
* limit: parseInt(params.get('limit') || '10', 10),
|
|
14466
|
+
* name: params.get('name') || undefined,
|
|
14467
|
+
* status: params.get('status') || undefined,
|
|
14468
|
+
* }),
|
|
14469
|
+
* serializeFilters: (filters, params) => {
|
|
14470
|
+
* if (filters.page) params.set('page', String(filters.page));
|
|
14471
|
+
* if (filters.limit) params.set('limit', String(filters.limit));
|
|
14472
|
+
* if (filters.name) params.set('name', filters.name);
|
|
14473
|
+
* if (filters.status) params.set('status', filters.status);
|
|
14474
|
+
* },
|
|
14475
|
+
* });
|
|
14476
|
+
* ```
|
|
14477
|
+
*/
|
|
14478
|
+
function useUrlFilters(options) {
|
|
14479
|
+
const {
|
|
14480
|
+
defaultPageSize = DEFAULT_PAGE_SIZE,
|
|
14481
|
+
parseFilters,
|
|
14482
|
+
serializeFilters,
|
|
14483
|
+
hasActiveFilters: checkActiveFilters,
|
|
14484
|
+
toApiParams
|
|
14485
|
+
} = options;
|
|
14486
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
14487
|
+
const filters = useMemo(() => {
|
|
14488
|
+
const parsed = parseFilters(searchParams);
|
|
14489
|
+
|
|
14490
|
+
// Ensure page and limit are always present with valid defaults
|
|
14491
|
+
const page = typeof parsed.page === "number" && parsed.page > 0 ? parsed.page : 1;
|
|
14492
|
+
const limit = typeof parsed.limit === "number" && parsed.limit > 0 ? parsed.limit : defaultPageSize;
|
|
14493
|
+
return {
|
|
14494
|
+
...parsed,
|
|
14495
|
+
page,
|
|
14496
|
+
limit
|
|
14497
|
+
};
|
|
14498
|
+
}, [searchParams, parseFilters, defaultPageSize]);
|
|
14499
|
+
const updateFilters = newFilters => {
|
|
14500
|
+
const params = new URLSearchParams(searchParams);
|
|
14501
|
+
|
|
14502
|
+
// Merge new filters with existing filters
|
|
14503
|
+
const mergedFilters = {
|
|
14504
|
+
...filters,
|
|
14505
|
+
...newFilters
|
|
14506
|
+
};
|
|
14507
|
+
|
|
14508
|
+
// Determine if we should reset page to 1
|
|
14509
|
+
// Reset if: page is not explicitly set AND other filters are changing
|
|
14510
|
+
const hasNonPaginationChanges = Object.keys(newFilters).some(key => key !== "page" && key !== "limit");
|
|
14511
|
+
if (newFilters.page === undefined && hasNonPaginationChanges) {
|
|
14512
|
+
mergedFilters.page = 1; // Reset to page 1
|
|
14513
|
+
}
|
|
14514
|
+
|
|
14515
|
+
// Ensure page and limit are numbers
|
|
14516
|
+
if (typeof mergedFilters.page !== "number" || mergedFilters.page < 1) {
|
|
14517
|
+
mergedFilters.page = 1;
|
|
14518
|
+
}
|
|
14519
|
+
if (typeof mergedFilters.limit !== "number" || mergedFilters.limit < 1) {
|
|
14520
|
+
mergedFilters.limit = defaultPageSize;
|
|
14521
|
+
}
|
|
14522
|
+
|
|
14523
|
+
// Serialize all filters
|
|
14524
|
+
serializeFilters(mergedFilters, params);
|
|
14525
|
+
setSearchParams(params, {
|
|
14526
|
+
replace: true
|
|
14527
|
+
});
|
|
14528
|
+
};
|
|
14529
|
+
const clearFilters = () => {
|
|
14530
|
+
const params = new URLSearchParams();
|
|
14531
|
+
params.set("page", "1");
|
|
14532
|
+
params.set("limit", String(defaultPageSize));
|
|
14533
|
+
setSearchParams(params, {
|
|
14534
|
+
replace: true
|
|
14535
|
+
});
|
|
14536
|
+
};
|
|
14537
|
+
const hasActiveFilters = useMemo(() => {
|
|
14538
|
+
if (checkActiveFilters) {
|
|
14539
|
+
return checkActiveFilters(filters);
|
|
14540
|
+
}
|
|
14541
|
+
// Default: check if any non-pagination fields have values
|
|
14542
|
+
return Object.keys(filters).some(key => {
|
|
14543
|
+
if (key === "page" || key === "limit") return false;
|
|
14544
|
+
const value = filters[key];
|
|
14545
|
+
return value !== undefined && value !== null && value !== "";
|
|
14546
|
+
});
|
|
14547
|
+
}, [filters, checkActiveFilters]);
|
|
14548
|
+
const apiParams = useMemo(() => {
|
|
14549
|
+
if (toApiParams) {
|
|
14550
|
+
return toApiParams(filters);
|
|
14551
|
+
}
|
|
14552
|
+
return undefined;
|
|
14553
|
+
}, [filters, toApiParams]);
|
|
14554
|
+
return {
|
|
14555
|
+
filters,
|
|
14556
|
+
updateFilters,
|
|
14557
|
+
clearFilters,
|
|
14558
|
+
hasActiveFilters,
|
|
14559
|
+
apiParams
|
|
14560
|
+
};
|
|
14561
|
+
}
|
|
14562
|
+
|
|
14427
14563
|
class ApiClient {
|
|
14428
14564
|
constructor(config) {
|
|
14429
14565
|
const {
|
|
@@ -14527,4 +14663,101 @@ const ModalContentWrapper = _ref => {
|
|
|
14527
14663
|
}, children));
|
|
14528
14664
|
};
|
|
14529
14665
|
|
|
14530
|
-
|
|
14666
|
+
/**
|
|
14667
|
+
* Default QueryClient configuration
|
|
14668
|
+
*/
|
|
14669
|
+
const defaultQueryClient = new QueryClient({
|
|
14670
|
+
defaultOptions: {
|
|
14671
|
+
queries: {
|
|
14672
|
+
retry: 1,
|
|
14673
|
+
refetchOnWindowFocus: false,
|
|
14674
|
+
staleTime: 30000,
|
|
14675
|
+
// 30 seconds
|
|
14676
|
+
gcTime: 5 * 60 * 1000 // 5 minutes
|
|
14677
|
+
},
|
|
14678
|
+
mutations: {
|
|
14679
|
+
retry: false
|
|
14680
|
+
}
|
|
14681
|
+
}
|
|
14682
|
+
});
|
|
14683
|
+
/**
|
|
14684
|
+
* Higher-order component that wraps a component with all necessary providers:
|
|
14685
|
+
* - QueryClientProvider (React Query)
|
|
14686
|
+
* - MantineProvider (Mantine UI)
|
|
14687
|
+
* - DatesProvider (Mantine Dates)
|
|
14688
|
+
*
|
|
14689
|
+
* @param Component - Component to wrap
|
|
14690
|
+
* @param options - Optional configuration
|
|
14691
|
+
* @returns Wrapped component with all providers
|
|
14692
|
+
*
|
|
14693
|
+
* @example
|
|
14694
|
+
* ```tsx
|
|
14695
|
+
* // Using default configuration
|
|
14696
|
+
* const WrappedComponent = withProviders(MyComponent);
|
|
14697
|
+
*
|
|
14698
|
+
* // Using custom QueryClient
|
|
14699
|
+
* const customQueryClient = new QueryClient({ ... });
|
|
14700
|
+
* const WrappedComponent = withProviders(MyComponent, {
|
|
14701
|
+
* queryClient: customQueryClient,
|
|
14702
|
+
* });
|
|
14703
|
+
* ```
|
|
14704
|
+
*/
|
|
14705
|
+
function withProviders(Component) {
|
|
14706
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
14707
|
+
const {
|
|
14708
|
+
queryClient = defaultQueryClient,
|
|
14709
|
+
enableDevtools = true,
|
|
14710
|
+
theme: customTheme = theme,
|
|
14711
|
+
datesSettings = {
|
|
14712
|
+
locale: "en",
|
|
14713
|
+
timezone: "UTC"
|
|
14714
|
+
}
|
|
14715
|
+
} = options;
|
|
14716
|
+
const WrappedComponent = props => {
|
|
14717
|
+
const showDevtools = enableDevtools && typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
14718
|
+
return /*#__PURE__*/React.createElement(QueryClientProvider, {
|
|
14719
|
+
client: queryClient
|
|
14720
|
+
}, /*#__PURE__*/React.createElement(MantineProvider, {
|
|
14721
|
+
theme: customTheme
|
|
14722
|
+
}, /*#__PURE__*/React.createElement(DatesProvider, {
|
|
14723
|
+
settings: datesSettings
|
|
14724
|
+
}, /*#__PURE__*/React.createElement(Component, props), showDevtools && /*#__PURE__*/React.createElement(ReactQueryDevtools, null))));
|
|
14725
|
+
};
|
|
14726
|
+
WrappedComponent.displayName = `withProviders(${Component.displayName || Component.name || "Component"})`;
|
|
14727
|
+
return WrappedComponent;
|
|
14728
|
+
}
|
|
14729
|
+
|
|
14730
|
+
/**
|
|
14731
|
+
* String utility functions for text manipulation
|
|
14732
|
+
*/
|
|
14733
|
+
const StringHelpers = {
|
|
14734
|
+
/**
|
|
14735
|
+
* Extracts text between curly braces from a string
|
|
14736
|
+
* @param input - Input string that may contain text in braces
|
|
14737
|
+
* @returns The text between braces, or empty string if not found
|
|
14738
|
+
* @example
|
|
14739
|
+
* extractBetweenBraces("Hello {world}") // returns "world"
|
|
14740
|
+
* extractBetweenBraces("No braces") // returns ""
|
|
14741
|
+
*/
|
|
14742
|
+
extractBetweenBraces: input => {
|
|
14743
|
+
const regex = /^[^{]*\{([^}]*)\}[^{]*$/;
|
|
14744
|
+
const match = input.match(regex);
|
|
14745
|
+
return match ? match[1] : "";
|
|
14746
|
+
},
|
|
14747
|
+
/**
|
|
14748
|
+
* Removes text within curly braces from a string
|
|
14749
|
+
* @param input - Input string that may contain text in braces
|
|
14750
|
+
* @returns The string with braces and their content removed, trimmed
|
|
14751
|
+
* @example
|
|
14752
|
+
* extractOutsideBraces("Hello {world}") // returns "Hello"
|
|
14753
|
+
* extractOutsideBraces("No braces") // returns "No braces"
|
|
14754
|
+
*/
|
|
14755
|
+
extractOutsideBraces: input => {
|
|
14756
|
+
const regex = /\{[^}]*\}/g;
|
|
14757
|
+
return input.replace(regex, "").trim();
|
|
14758
|
+
}
|
|
14759
|
+
};
|
|
14760
|
+
const extractBetweenBraces = StringHelpers.extractBetweenBraces;
|
|
14761
|
+
const extractOutsideBraces = StringHelpers.extractOutsideBraces;
|
|
14762
|
+
|
|
14763
|
+
export { extractOutsideBraces as $, ApplicationMenu as A, BasicHeatmap as B, CalendarHeatmap as C, DonutChart as D, EqualizerColumn as E, File as F, SimpleForm as G, MaskedTilePanel as H, InterpolatedHeatmap as I, TilePanel as J, useModal as K, LabelPanel as L, MultiAxisArea as M, useManagedModals as N, useUrlFilters as O, PageTitle as P, DEFAULT_PAGE_SIZE as Q, MAX_PAGE_SIZE as R, SimpleColumn as S, TitledPanel as T, UserMenu as U, DEFAULT_API_TIMEOUT as V, createApiClient as W, apiClient as X, ModalContentWrapper as Y, withProviders as Z, extractBetweenBraces as _, StackedColumn as a, SimpleArea as b, StackedArea as c, Icons as d, DynamicLogo as e, DynamicShigaLogo as f, getDefaultExportFromCjs as g, SideMenu as h, SimplePanel as i, SearchPanel as j, AvatarLabelPanel as k, SimpleText as l, TitleWithIndex as m, ConnectionPanel as n, ApplicationPanel as o, SubscriptionPlans as p, PaymentMethod as q, PaymentMethodAdd as r, SimpleTable as s, theme as t, ErrorModal as u, InfoModal as v, SimpleModal as w, SuccessModal as x, TwoFactorModal as y, Drawer as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApplicationMenu, o as ApplicationPanel, k as AvatarLabelPanel, B as BasicHeatmap, C as CalendarHeatmap, n as ConnectionPanel,
|
|
1
|
+
export { A as ApplicationMenu, o as ApplicationPanel, k as AvatarLabelPanel, B as BasicHeatmap, C as CalendarHeatmap, n as ConnectionPanel, V as DEFAULT_API_TIMEOUT, Q as DEFAULT_PAGE_SIZE, D as DonutChart, z as Drawer, e as DynamicLogo, f as DynamicShigaLogo, E as EqualizerColumn, u as ErrorModal, F as File, d as Icons, v as InfoModal, I as InterpolatedHeatmap, L as LabelPanel, R as MAX_PAGE_SIZE, H as MaskedTilePanel, Y as ModalContentWrapper, M as MultiAxisArea, P as PageTitle, q as PaymentMethod, r as PaymentMethodAdd, j as SearchPanel, h as SideMenu, b as SimpleArea, S as SimpleColumn, G as SimpleForm, w as SimpleModal, i as SimplePanel, s as SimpleTable, l as SimpleText, c as StackedArea, a as StackedColumn, p as SubscriptionPlans, x as SuccessModal, J as TilePanel, m as TitleWithIndex, T as TitledPanel, y as TwoFactorModal, U as UserMenu, X as apiClient, W as createApiClient, _ as extractBetweenBraces, $ as extractOutsideBraces, t as theme, N as useManagedModals, K as useModal, O as useUrlFilters, Z as withProviders } from './index-BlLQ1b_6.js';
|
|
2
2
|
import '@mantine/modals';
|
|
3
3
|
import 'react';
|
|
4
4
|
import '@mantine/core';
|
|
@@ -21,3 +21,5 @@ import '@fontsource/poppins/800.css';
|
|
|
21
21
|
import 'axios';
|
|
22
22
|
import '@mantine/dates';
|
|
23
23
|
import '@mantine/dates/styles.css';
|
|
24
|
+
import '@tanstack/react-query';
|
|
25
|
+
import '@tanstack/react-query-devtools';
|
package/build/typings/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export * from "./components";
|
|
2
2
|
export * from "./shared/hooks/modals/useModal";
|
|
3
3
|
export * from "./shared/hooks/modals/useManagedModals";
|
|
4
|
+
export * from "./shared/hooks";
|
|
4
5
|
export * from "./shared/api";
|
|
5
6
|
export * from "./shared/components";
|
|
7
|
+
export * from "./shared/types";
|
|
8
|
+
export * from "./shared/hocs";
|
|
9
|
+
export * from "./shared/utils";
|
|
@@ -14,3 +14,13 @@ export interface ApiError {
|
|
|
14
14
|
message: string;
|
|
15
15
|
error: string;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Paginated API response
|
|
19
|
+
* Combines ApiResponse structure with pagination metadata
|
|
20
|
+
*/
|
|
21
|
+
export interface PaginatedApiResponse<T> extends Omit<ApiResponse<T[]>, "data" | "total" | "page" | "limit"> {
|
|
22
|
+
data: T[];
|
|
23
|
+
total: number;
|
|
24
|
+
page: number;
|
|
25
|
+
limit: number;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./withProviders";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { theme } from "../../components/theme";
|
|
3
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
4
|
+
import "@mantine/dates/styles.css";
|
|
5
|
+
export interface WithProvidersOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Custom QueryClient instance (optional)
|
|
8
|
+
* If not provided, uses default configuration
|
|
9
|
+
*/
|
|
10
|
+
queryClient?: QueryClient;
|
|
11
|
+
/**
|
|
12
|
+
* Whether to show React Query Devtools in development (default: true)
|
|
13
|
+
*/
|
|
14
|
+
enableDevtools?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Mantine theme override (optional)
|
|
17
|
+
*/
|
|
18
|
+
theme?: typeof theme;
|
|
19
|
+
/**
|
|
20
|
+
* DatesProvider settings override (optional)
|
|
21
|
+
*/
|
|
22
|
+
datesSettings?: {
|
|
23
|
+
locale: string;
|
|
24
|
+
timezone: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Higher-order component that wraps a component with all necessary providers:
|
|
29
|
+
* - QueryClientProvider (React Query)
|
|
30
|
+
* - MantineProvider (Mantine UI)
|
|
31
|
+
* - DatesProvider (Mantine Dates)
|
|
32
|
+
*
|
|
33
|
+
* @param Component - Component to wrap
|
|
34
|
+
* @param options - Optional configuration
|
|
35
|
+
* @returns Wrapped component with all providers
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Using default configuration
|
|
40
|
+
* const WrappedComponent = withProviders(MyComponent);
|
|
41
|
+
*
|
|
42
|
+
* // Using custom QueryClient
|
|
43
|
+
* const customQueryClient = new QueryClient({ ... });
|
|
44
|
+
* const WrappedComponent = withProviders(MyComponent, {
|
|
45
|
+
* queryClient: customQueryClient,
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function withProviders<P extends object>(Component: React.ComponentType<P>, options?: WithProvidersOptions): React.ComponentType<P>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useUrlFilters";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for URL filter hook
|
|
3
|
+
*/
|
|
4
|
+
export interface UseUrlFiltersOptions<TFilters extends Record<string, any>> {
|
|
5
|
+
/**
|
|
6
|
+
* Default page size (defaults to DEFAULT_PAGE_SIZE from constants)
|
|
7
|
+
*/
|
|
8
|
+
defaultPageSize?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Function to parse filter values from URL search params
|
|
11
|
+
* @param searchParams - URLSearchParams object
|
|
12
|
+
* @returns Parsed filter object
|
|
13
|
+
*/
|
|
14
|
+
parseFilters: (searchParams: URLSearchParams) => Partial<TFilters>;
|
|
15
|
+
/**
|
|
16
|
+
* Function to serialize filter values to URL search params
|
|
17
|
+
* @param filters - Filter object
|
|
18
|
+
* @param params - URLSearchParams object to update
|
|
19
|
+
*/
|
|
20
|
+
serializeFilters: (filters: Partial<TFilters>, params: URLSearchParams) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Function to check if any filters are active (excluding pagination)
|
|
23
|
+
* @param filters - Filter object
|
|
24
|
+
* @returns true if any filters are active
|
|
25
|
+
*/
|
|
26
|
+
hasActiveFilters?: (filters: TFilters) => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Function to convert filters to API parameters
|
|
29
|
+
* @param filters - Filter object
|
|
30
|
+
* @returns API parameters object
|
|
31
|
+
*/
|
|
32
|
+
toApiParams?: (filters: TFilters) => Record<string, any>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Return type for useUrlFilters hook
|
|
36
|
+
*/
|
|
37
|
+
export interface UseUrlFiltersReturn<TFilters extends Record<string, any>> {
|
|
38
|
+
/**
|
|
39
|
+
* Current filter values (includes page and limit)
|
|
40
|
+
*/
|
|
41
|
+
filters: TFilters;
|
|
42
|
+
/**
|
|
43
|
+
* Update filters in URL
|
|
44
|
+
* @param newFilters - Partial filter object to update
|
|
45
|
+
*/
|
|
46
|
+
updateFilters: (newFilters: Partial<TFilters>) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Clear all filters (resets to default page and limit)
|
|
49
|
+
*/
|
|
50
|
+
clearFilters: () => void;
|
|
51
|
+
/**
|
|
52
|
+
* Whether any filters are currently active (excluding pagination)
|
|
53
|
+
*/
|
|
54
|
+
hasActiveFilters: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* API parameters derived from filters (if toApiParams provided)
|
|
57
|
+
*/
|
|
58
|
+
apiParams?: Record<string, any>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generic hook for managing URL-based filters with pagination
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* interface MyFilters {
|
|
66
|
+
* page: number;
|
|
67
|
+
* limit: number;
|
|
68
|
+
* name?: string;
|
|
69
|
+
* status?: string;
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* const { filters, updateFilters, clearFilters } = useUrlFilters<MyFilters>({
|
|
73
|
+
* parseFilters: (params) => ({
|
|
74
|
+
* page: parseInt(params.get('page') || '1', 10),
|
|
75
|
+
* limit: parseInt(params.get('limit') || '10', 10),
|
|
76
|
+
* name: params.get('name') || undefined,
|
|
77
|
+
* status: params.get('status') || undefined,
|
|
78
|
+
* }),
|
|
79
|
+
* serializeFilters: (filters, params) => {
|
|
80
|
+
* if (filters.page) params.set('page', String(filters.page));
|
|
81
|
+
* if (filters.limit) params.set('limit', String(filters.limit));
|
|
82
|
+
* if (filters.name) params.set('name', filters.name);
|
|
83
|
+
* if (filters.status) params.set('status', filters.status);
|
|
84
|
+
* },
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare function useUrlFilters<TFilters extends Record<string, any>>(options: UseUrlFiltersOptions<TFilters>): UseUrlFiltersReturn<TFilters>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./pagination";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard pagination parameters for API requests
|
|
3
|
+
*/
|
|
4
|
+
export interface PaginationParams {
|
|
5
|
+
page?: number;
|
|
6
|
+
limit?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Standard paginated response structure
|
|
10
|
+
*/
|
|
11
|
+
export interface PaginatedResponse<T> {
|
|
12
|
+
data: T[];
|
|
13
|
+
total: number;
|
|
14
|
+
page: number;
|
|
15
|
+
limit: number;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./stringHelpers";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adiba-banking-cloud/backoffice",
|
|
3
3
|
"author": "TUROG Technologies",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"description": "An ADIBA component library for backoffice and dashboard applications",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"main": "build/index.cjs.js",
|
|
@@ -42,13 +42,17 @@
|
|
|
42
42
|
"iconsax-react": "^0.0.8",
|
|
43
43
|
"react": ">=18",
|
|
44
44
|
"react-dom": ">=18",
|
|
45
|
-
"react-router-dom": "^7.6.2"
|
|
45
|
+
"react-router-dom": "^7.6.2",
|
|
46
|
+
"@tanstack/react-query": "^5.0.0",
|
|
47
|
+
"@tanstack/react-query-devtools": "^5.0.0"
|
|
46
48
|
},
|
|
47
49
|
"repository": {
|
|
48
50
|
"type": "git",
|
|
49
51
|
"url": "git+https://github.com/turog-technologies/adiba-common-libraries.git"
|
|
50
52
|
},
|
|
51
53
|
"devDependencies": {
|
|
54
|
+
"@tanstack/react-query": "^5.0.0",
|
|
55
|
+
"@tanstack/react-query-devtools": "^5.0.0",
|
|
52
56
|
"axios": "^1.6.0",
|
|
53
57
|
"@babel/core": "^7.21.3",
|
|
54
58
|
"@babel/plugin-transform-runtime": "^7.21.0",
|