@adiba-banking-cloud/backoffice 0.2.0 → 0.2.1
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-D-qDlLOI.js} +1 -1
- package/build/index.cjs.js/{index-QwR6crYB.js → index-CWyl7EKZ.js} +190 -1
- package/build/index.cjs.js/index.js +5 -1
- package/build/index.esm.js/{heatmap-Dfb5-pNh.js → heatmap-CtdCSRhG.js} +1 -1
- package/build/index.esm.js/{index-9HtrJaD9.js → index-D7Cza3cb.js} +190 -3
- package/build/index.esm.js/index.js +3 -1
- package/build/typings/index.d.ts +3 -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/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-D-qDlLOI.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);
|
|
@@ -14445,6 +14447,127 @@ const MAX_PAGE_SIZE = 100;
|
|
|
14445
14447
|
*/
|
|
14446
14448
|
const DEFAULT_API_TIMEOUT = 30000;
|
|
14447
14449
|
|
|
14450
|
+
/**
|
|
14451
|
+
* Configuration for URL filter hook
|
|
14452
|
+
*/
|
|
14453
|
+
|
|
14454
|
+
/**
|
|
14455
|
+
* Return type for useUrlFilters hook
|
|
14456
|
+
*/
|
|
14457
|
+
|
|
14458
|
+
/**
|
|
14459
|
+
* Generic hook for managing URL-based filters with pagination
|
|
14460
|
+
*
|
|
14461
|
+
* @example
|
|
14462
|
+
* ```tsx
|
|
14463
|
+
* interface MyFilters {
|
|
14464
|
+
* page: number;
|
|
14465
|
+
* limit: number;
|
|
14466
|
+
* name?: string;
|
|
14467
|
+
* status?: string;
|
|
14468
|
+
* }
|
|
14469
|
+
*
|
|
14470
|
+
* const { filters, updateFilters, clearFilters } = useUrlFilters<MyFilters>({
|
|
14471
|
+
* parseFilters: (params) => ({
|
|
14472
|
+
* page: parseInt(params.get('page') || '1', 10),
|
|
14473
|
+
* limit: parseInt(params.get('limit') || '10', 10),
|
|
14474
|
+
* name: params.get('name') || undefined,
|
|
14475
|
+
* status: params.get('status') || undefined,
|
|
14476
|
+
* }),
|
|
14477
|
+
* serializeFilters: (filters, params) => {
|
|
14478
|
+
* if (filters.page) params.set('page', String(filters.page));
|
|
14479
|
+
* if (filters.limit) params.set('limit', String(filters.limit));
|
|
14480
|
+
* if (filters.name) params.set('name', filters.name);
|
|
14481
|
+
* if (filters.status) params.set('status', filters.status);
|
|
14482
|
+
* },
|
|
14483
|
+
* });
|
|
14484
|
+
* ```
|
|
14485
|
+
*/
|
|
14486
|
+
function useUrlFilters(options) {
|
|
14487
|
+
const {
|
|
14488
|
+
defaultPageSize = DEFAULT_PAGE_SIZE,
|
|
14489
|
+
parseFilters,
|
|
14490
|
+
serializeFilters,
|
|
14491
|
+
hasActiveFilters: checkActiveFilters,
|
|
14492
|
+
toApiParams
|
|
14493
|
+
} = options;
|
|
14494
|
+
const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
|
|
14495
|
+
const filters = React.useMemo(() => {
|
|
14496
|
+
const parsed = parseFilters(searchParams);
|
|
14497
|
+
|
|
14498
|
+
// Ensure page and limit are always present with valid defaults
|
|
14499
|
+
const page = typeof parsed.page === "number" && parsed.page > 0 ? parsed.page : 1;
|
|
14500
|
+
const limit = typeof parsed.limit === "number" && parsed.limit > 0 ? parsed.limit : defaultPageSize;
|
|
14501
|
+
return {
|
|
14502
|
+
...parsed,
|
|
14503
|
+
page,
|
|
14504
|
+
limit
|
|
14505
|
+
};
|
|
14506
|
+
}, [searchParams, parseFilters, defaultPageSize]);
|
|
14507
|
+
const updateFilters = newFilters => {
|
|
14508
|
+
const params = new URLSearchParams(searchParams);
|
|
14509
|
+
|
|
14510
|
+
// Merge new filters with existing filters
|
|
14511
|
+
const mergedFilters = {
|
|
14512
|
+
...filters,
|
|
14513
|
+
...newFilters
|
|
14514
|
+
};
|
|
14515
|
+
|
|
14516
|
+
// Determine if we should reset page to 1
|
|
14517
|
+
// Reset if: page is not explicitly set AND other filters are changing
|
|
14518
|
+
const hasNonPaginationChanges = Object.keys(newFilters).some(key => key !== "page" && key !== "limit");
|
|
14519
|
+
if (newFilters.page === undefined && hasNonPaginationChanges) {
|
|
14520
|
+
mergedFilters.page = 1; // Reset to page 1
|
|
14521
|
+
}
|
|
14522
|
+
|
|
14523
|
+
// Ensure page and limit are numbers
|
|
14524
|
+
if (typeof mergedFilters.page !== "number" || mergedFilters.page < 1) {
|
|
14525
|
+
mergedFilters.page = 1;
|
|
14526
|
+
}
|
|
14527
|
+
if (typeof mergedFilters.limit !== "number" || mergedFilters.limit < 1) {
|
|
14528
|
+
mergedFilters.limit = defaultPageSize;
|
|
14529
|
+
}
|
|
14530
|
+
|
|
14531
|
+
// Serialize all filters
|
|
14532
|
+
serializeFilters(mergedFilters, params);
|
|
14533
|
+
setSearchParams(params, {
|
|
14534
|
+
replace: true
|
|
14535
|
+
});
|
|
14536
|
+
};
|
|
14537
|
+
const clearFilters = () => {
|
|
14538
|
+
const params = new URLSearchParams();
|
|
14539
|
+
params.set("page", "1");
|
|
14540
|
+
params.set("limit", String(defaultPageSize));
|
|
14541
|
+
setSearchParams(params, {
|
|
14542
|
+
replace: true
|
|
14543
|
+
});
|
|
14544
|
+
};
|
|
14545
|
+
const hasActiveFilters = React.useMemo(() => {
|
|
14546
|
+
if (checkActiveFilters) {
|
|
14547
|
+
return checkActiveFilters(filters);
|
|
14548
|
+
}
|
|
14549
|
+
// Default: check if any non-pagination fields have values
|
|
14550
|
+
return Object.keys(filters).some(key => {
|
|
14551
|
+
if (key === "page" || key === "limit") return false;
|
|
14552
|
+
const value = filters[key];
|
|
14553
|
+
return value !== undefined && value !== null && value !== "";
|
|
14554
|
+
});
|
|
14555
|
+
}, [filters, checkActiveFilters]);
|
|
14556
|
+
const apiParams = React.useMemo(() => {
|
|
14557
|
+
if (toApiParams) {
|
|
14558
|
+
return toApiParams(filters);
|
|
14559
|
+
}
|
|
14560
|
+
return undefined;
|
|
14561
|
+
}, [filters, toApiParams]);
|
|
14562
|
+
return {
|
|
14563
|
+
filters,
|
|
14564
|
+
updateFilters,
|
|
14565
|
+
clearFilters,
|
|
14566
|
+
hasActiveFilters,
|
|
14567
|
+
apiParams
|
|
14568
|
+
};
|
|
14569
|
+
}
|
|
14570
|
+
|
|
14448
14571
|
class ApiClient {
|
|
14449
14572
|
constructor(config) {
|
|
14450
14573
|
const {
|
|
@@ -14548,6 +14671,70 @@ const ModalContentWrapper = _ref => {
|
|
|
14548
14671
|
}, children));
|
|
14549
14672
|
};
|
|
14550
14673
|
|
|
14674
|
+
/**
|
|
14675
|
+
* Default QueryClient configuration
|
|
14676
|
+
*/
|
|
14677
|
+
const defaultQueryClient = new reactQuery.QueryClient({
|
|
14678
|
+
defaultOptions: {
|
|
14679
|
+
queries: {
|
|
14680
|
+
retry: 1,
|
|
14681
|
+
refetchOnWindowFocus: false,
|
|
14682
|
+
staleTime: 30000,
|
|
14683
|
+
// 30 seconds
|
|
14684
|
+
gcTime: 5 * 60 * 1000 // 5 minutes
|
|
14685
|
+
},
|
|
14686
|
+
mutations: {
|
|
14687
|
+
retry: false
|
|
14688
|
+
}
|
|
14689
|
+
}
|
|
14690
|
+
});
|
|
14691
|
+
/**
|
|
14692
|
+
* Higher-order component that wraps a component with all necessary providers:
|
|
14693
|
+
* - QueryClientProvider (React Query)
|
|
14694
|
+
* - MantineProvider (Mantine UI)
|
|
14695
|
+
* - DatesProvider (Mantine Dates)
|
|
14696
|
+
*
|
|
14697
|
+
* @param Component - Component to wrap
|
|
14698
|
+
* @param options - Optional configuration
|
|
14699
|
+
* @returns Wrapped component with all providers
|
|
14700
|
+
*
|
|
14701
|
+
* @example
|
|
14702
|
+
* ```tsx
|
|
14703
|
+
* // Using default configuration
|
|
14704
|
+
* const WrappedComponent = withProviders(MyComponent);
|
|
14705
|
+
*
|
|
14706
|
+
* // Using custom QueryClient
|
|
14707
|
+
* const customQueryClient = new QueryClient({ ... });
|
|
14708
|
+
* const WrappedComponent = withProviders(MyComponent, {
|
|
14709
|
+
* queryClient: customQueryClient,
|
|
14710
|
+
* });
|
|
14711
|
+
* ```
|
|
14712
|
+
*/
|
|
14713
|
+
function withProviders(Component) {
|
|
14714
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
14715
|
+
const {
|
|
14716
|
+
queryClient = defaultQueryClient,
|
|
14717
|
+
enableDevtools = true,
|
|
14718
|
+
theme: customTheme = theme,
|
|
14719
|
+
datesSettings = {
|
|
14720
|
+
locale: "en",
|
|
14721
|
+
timezone: "UTC"
|
|
14722
|
+
}
|
|
14723
|
+
} = options;
|
|
14724
|
+
const WrappedComponent = props => {
|
|
14725
|
+
const showDevtools = enableDevtools && typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
14726
|
+
return /*#__PURE__*/React__namespace.createElement(reactQuery.QueryClientProvider, {
|
|
14727
|
+
client: queryClient
|
|
14728
|
+
}, /*#__PURE__*/React__namespace.createElement(core.MantineProvider, {
|
|
14729
|
+
theme: customTheme
|
|
14730
|
+
}, /*#__PURE__*/React__namespace.createElement(dates.DatesProvider, {
|
|
14731
|
+
settings: datesSettings
|
|
14732
|
+
}, /*#__PURE__*/React__namespace.createElement(Component, props), showDevtools && /*#__PURE__*/React__namespace.createElement(reactQueryDevtools.ReactQueryDevtools, null))));
|
|
14733
|
+
};
|
|
14734
|
+
WrappedComponent.displayName = `withProviders(${Component.displayName || Component.name || "Component"})`;
|
|
14735
|
+
return WrappedComponent;
|
|
14736
|
+
}
|
|
14737
|
+
|
|
14551
14738
|
exports.ApplicationMenu = ApplicationMenu;
|
|
14552
14739
|
exports.ApplicationPanel = ApplicationPanel;
|
|
14553
14740
|
exports.AvatarLabelPanel = AvatarLabelPanel;
|
|
@@ -14598,3 +14785,5 @@ exports.getDefaultExportFromCjs = getDefaultExportFromCjs;
|
|
|
14598
14785
|
exports.theme = theme;
|
|
14599
14786
|
exports.useManagedModals = useManagedModals;
|
|
14600
14787
|
exports.useModal = useModal;
|
|
14788
|
+
exports.useUrlFilters = useUrlFilters;
|
|
14789
|
+
exports.withProviders = withProviders;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-CWyl7EKZ.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
|
|
|
@@ -75,3 +77,5 @@ exports.createApiClient = index.createApiClient;
|
|
|
75
77
|
exports.theme = index.theme;
|
|
76
78
|
exports.useManagedModals = index.useManagedModals;
|
|
77
79
|
exports.useModal = index.useModal;
|
|
80
|
+
exports.useUrlFilters = index.useUrlFilters;
|
|
81
|
+
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-CtdCSRhG.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);
|
|
@@ -14424,6 +14426,127 @@ const MAX_PAGE_SIZE = 100;
|
|
|
14424
14426
|
*/
|
|
14425
14427
|
const DEFAULT_API_TIMEOUT = 30000;
|
|
14426
14428
|
|
|
14429
|
+
/**
|
|
14430
|
+
* Configuration for URL filter hook
|
|
14431
|
+
*/
|
|
14432
|
+
|
|
14433
|
+
/**
|
|
14434
|
+
* Return type for useUrlFilters hook
|
|
14435
|
+
*/
|
|
14436
|
+
|
|
14437
|
+
/**
|
|
14438
|
+
* Generic hook for managing URL-based filters with pagination
|
|
14439
|
+
*
|
|
14440
|
+
* @example
|
|
14441
|
+
* ```tsx
|
|
14442
|
+
* interface MyFilters {
|
|
14443
|
+
* page: number;
|
|
14444
|
+
* limit: number;
|
|
14445
|
+
* name?: string;
|
|
14446
|
+
* status?: string;
|
|
14447
|
+
* }
|
|
14448
|
+
*
|
|
14449
|
+
* const { filters, updateFilters, clearFilters } = useUrlFilters<MyFilters>({
|
|
14450
|
+
* parseFilters: (params) => ({
|
|
14451
|
+
* page: parseInt(params.get('page') || '1', 10),
|
|
14452
|
+
* limit: parseInt(params.get('limit') || '10', 10),
|
|
14453
|
+
* name: params.get('name') || undefined,
|
|
14454
|
+
* status: params.get('status') || undefined,
|
|
14455
|
+
* }),
|
|
14456
|
+
* serializeFilters: (filters, params) => {
|
|
14457
|
+
* if (filters.page) params.set('page', String(filters.page));
|
|
14458
|
+
* if (filters.limit) params.set('limit', String(filters.limit));
|
|
14459
|
+
* if (filters.name) params.set('name', filters.name);
|
|
14460
|
+
* if (filters.status) params.set('status', filters.status);
|
|
14461
|
+
* },
|
|
14462
|
+
* });
|
|
14463
|
+
* ```
|
|
14464
|
+
*/
|
|
14465
|
+
function useUrlFilters(options) {
|
|
14466
|
+
const {
|
|
14467
|
+
defaultPageSize = DEFAULT_PAGE_SIZE,
|
|
14468
|
+
parseFilters,
|
|
14469
|
+
serializeFilters,
|
|
14470
|
+
hasActiveFilters: checkActiveFilters,
|
|
14471
|
+
toApiParams
|
|
14472
|
+
} = options;
|
|
14473
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
14474
|
+
const filters = useMemo(() => {
|
|
14475
|
+
const parsed = parseFilters(searchParams);
|
|
14476
|
+
|
|
14477
|
+
// Ensure page and limit are always present with valid defaults
|
|
14478
|
+
const page = typeof parsed.page === "number" && parsed.page > 0 ? parsed.page : 1;
|
|
14479
|
+
const limit = typeof parsed.limit === "number" && parsed.limit > 0 ? parsed.limit : defaultPageSize;
|
|
14480
|
+
return {
|
|
14481
|
+
...parsed,
|
|
14482
|
+
page,
|
|
14483
|
+
limit
|
|
14484
|
+
};
|
|
14485
|
+
}, [searchParams, parseFilters, defaultPageSize]);
|
|
14486
|
+
const updateFilters = newFilters => {
|
|
14487
|
+
const params = new URLSearchParams(searchParams);
|
|
14488
|
+
|
|
14489
|
+
// Merge new filters with existing filters
|
|
14490
|
+
const mergedFilters = {
|
|
14491
|
+
...filters,
|
|
14492
|
+
...newFilters
|
|
14493
|
+
};
|
|
14494
|
+
|
|
14495
|
+
// Determine if we should reset page to 1
|
|
14496
|
+
// Reset if: page is not explicitly set AND other filters are changing
|
|
14497
|
+
const hasNonPaginationChanges = Object.keys(newFilters).some(key => key !== "page" && key !== "limit");
|
|
14498
|
+
if (newFilters.page === undefined && hasNonPaginationChanges) {
|
|
14499
|
+
mergedFilters.page = 1; // Reset to page 1
|
|
14500
|
+
}
|
|
14501
|
+
|
|
14502
|
+
// Ensure page and limit are numbers
|
|
14503
|
+
if (typeof mergedFilters.page !== "number" || mergedFilters.page < 1) {
|
|
14504
|
+
mergedFilters.page = 1;
|
|
14505
|
+
}
|
|
14506
|
+
if (typeof mergedFilters.limit !== "number" || mergedFilters.limit < 1) {
|
|
14507
|
+
mergedFilters.limit = defaultPageSize;
|
|
14508
|
+
}
|
|
14509
|
+
|
|
14510
|
+
// Serialize all filters
|
|
14511
|
+
serializeFilters(mergedFilters, params);
|
|
14512
|
+
setSearchParams(params, {
|
|
14513
|
+
replace: true
|
|
14514
|
+
});
|
|
14515
|
+
};
|
|
14516
|
+
const clearFilters = () => {
|
|
14517
|
+
const params = new URLSearchParams();
|
|
14518
|
+
params.set("page", "1");
|
|
14519
|
+
params.set("limit", String(defaultPageSize));
|
|
14520
|
+
setSearchParams(params, {
|
|
14521
|
+
replace: true
|
|
14522
|
+
});
|
|
14523
|
+
};
|
|
14524
|
+
const hasActiveFilters = useMemo(() => {
|
|
14525
|
+
if (checkActiveFilters) {
|
|
14526
|
+
return checkActiveFilters(filters);
|
|
14527
|
+
}
|
|
14528
|
+
// Default: check if any non-pagination fields have values
|
|
14529
|
+
return Object.keys(filters).some(key => {
|
|
14530
|
+
if (key === "page" || key === "limit") return false;
|
|
14531
|
+
const value = filters[key];
|
|
14532
|
+
return value !== undefined && value !== null && value !== "";
|
|
14533
|
+
});
|
|
14534
|
+
}, [filters, checkActiveFilters]);
|
|
14535
|
+
const apiParams = useMemo(() => {
|
|
14536
|
+
if (toApiParams) {
|
|
14537
|
+
return toApiParams(filters);
|
|
14538
|
+
}
|
|
14539
|
+
return undefined;
|
|
14540
|
+
}, [filters, toApiParams]);
|
|
14541
|
+
return {
|
|
14542
|
+
filters,
|
|
14543
|
+
updateFilters,
|
|
14544
|
+
clearFilters,
|
|
14545
|
+
hasActiveFilters,
|
|
14546
|
+
apiParams
|
|
14547
|
+
};
|
|
14548
|
+
}
|
|
14549
|
+
|
|
14427
14550
|
class ApiClient {
|
|
14428
14551
|
constructor(config) {
|
|
14429
14552
|
const {
|
|
@@ -14527,4 +14650,68 @@ const ModalContentWrapper = _ref => {
|
|
|
14527
14650
|
}, children));
|
|
14528
14651
|
};
|
|
14529
14652
|
|
|
14530
|
-
|
|
14653
|
+
/**
|
|
14654
|
+
* Default QueryClient configuration
|
|
14655
|
+
*/
|
|
14656
|
+
const defaultQueryClient = new QueryClient({
|
|
14657
|
+
defaultOptions: {
|
|
14658
|
+
queries: {
|
|
14659
|
+
retry: 1,
|
|
14660
|
+
refetchOnWindowFocus: false,
|
|
14661
|
+
staleTime: 30000,
|
|
14662
|
+
// 30 seconds
|
|
14663
|
+
gcTime: 5 * 60 * 1000 // 5 minutes
|
|
14664
|
+
},
|
|
14665
|
+
mutations: {
|
|
14666
|
+
retry: false
|
|
14667
|
+
}
|
|
14668
|
+
}
|
|
14669
|
+
});
|
|
14670
|
+
/**
|
|
14671
|
+
* Higher-order component that wraps a component with all necessary providers:
|
|
14672
|
+
* - QueryClientProvider (React Query)
|
|
14673
|
+
* - MantineProvider (Mantine UI)
|
|
14674
|
+
* - DatesProvider (Mantine Dates)
|
|
14675
|
+
*
|
|
14676
|
+
* @param Component - Component to wrap
|
|
14677
|
+
* @param options - Optional configuration
|
|
14678
|
+
* @returns Wrapped component with all providers
|
|
14679
|
+
*
|
|
14680
|
+
* @example
|
|
14681
|
+
* ```tsx
|
|
14682
|
+
* // Using default configuration
|
|
14683
|
+
* const WrappedComponent = withProviders(MyComponent);
|
|
14684
|
+
*
|
|
14685
|
+
* // Using custom QueryClient
|
|
14686
|
+
* const customQueryClient = new QueryClient({ ... });
|
|
14687
|
+
* const WrappedComponent = withProviders(MyComponent, {
|
|
14688
|
+
* queryClient: customQueryClient,
|
|
14689
|
+
* });
|
|
14690
|
+
* ```
|
|
14691
|
+
*/
|
|
14692
|
+
function withProviders(Component) {
|
|
14693
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
14694
|
+
const {
|
|
14695
|
+
queryClient = defaultQueryClient,
|
|
14696
|
+
enableDevtools = true,
|
|
14697
|
+
theme: customTheme = theme,
|
|
14698
|
+
datesSettings = {
|
|
14699
|
+
locale: "en",
|
|
14700
|
+
timezone: "UTC"
|
|
14701
|
+
}
|
|
14702
|
+
} = options;
|
|
14703
|
+
const WrappedComponent = props => {
|
|
14704
|
+
const showDevtools = enableDevtools && typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
14705
|
+
return /*#__PURE__*/React.createElement(QueryClientProvider, {
|
|
14706
|
+
client: queryClient
|
|
14707
|
+
}, /*#__PURE__*/React.createElement(MantineProvider, {
|
|
14708
|
+
theme: customTheme
|
|
14709
|
+
}, /*#__PURE__*/React.createElement(DatesProvider, {
|
|
14710
|
+
settings: datesSettings
|
|
14711
|
+
}, /*#__PURE__*/React.createElement(Component, props), showDevtools && /*#__PURE__*/React.createElement(ReactQueryDevtools, null))));
|
|
14712
|
+
};
|
|
14713
|
+
WrappedComponent.displayName = `withProviders(${Component.displayName || Component.name || "Component"})`;
|
|
14714
|
+
return WrappedComponent;
|
|
14715
|
+
}
|
|
14716
|
+
|
|
14717
|
+
export { 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, 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, t as theme, N as useManagedModals, K as useModal, O as useUrlFilters, Z as withProviders } from './index-D7Cza3cb.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,8 @@
|
|
|
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";
|
|
@@ -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
|
+
}
|
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.1",
|
|
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",
|