diff --git a/payment-iq/app/features/AdvancedSearch/store/advancedSearchSlice.ts b/payment-iq/app/features/AdvancedSearch/store/advancedSearchSlice.ts
new file mode 100644
index 0000000..43b055c
--- /dev/null
+++ b/payment-iq/app/features/AdvancedSearch/store/advancedSearchSlice.ts
@@ -0,0 +1,56 @@
+import { createSlice } from '@reduxjs/toolkit';
+
+interface AdvancedSearchState {
+ keyword: string,
+ transactionID: string,
+ transactionReferenceId: string,
+ user: string,
+ currency: string,
+ state: string,
+ statusDescription: string,
+ transactionType: string,
+ paymentMethod: string,
+ psps: string,
+ initialPsps: string,
+ merchants: string,
+ startDate: null | string,
+ endDate: null | string,
+ lastUpdatedFrom: null | string,
+ lastUpdatedTo: null | string,
+ minAmount: string,
+ maxAmount: string,
+ channel: string,
+}
+
+const initialState: AdvancedSearchState = {
+ keyword: "",
+ transactionID: "",
+ transactionReferenceId: "",
+ user: "",
+ currency: "",
+ state: "",
+ statusDescription: "",
+ transactionType: "",
+ paymentMethod: "",
+ psps: "",
+ initialPsps: "",
+ merchants: "",
+ startDate: null,
+ endDate: null,
+ lastUpdatedFrom: null,
+ lastUpdatedTo: null,
+ minAmount: "",
+ maxAmount: "",
+ channel: "",
+};
+
+const advancedSearchSlice = createSlice({
+ name: 'advancedSearch',
+ initialState,
+ reducers: {
+ },
+},
+);
+
+export default advancedSearchSlice.reducer;
+
diff --git a/payment-iq/app/features/Pages/transactions/Transactions.tsx b/payment-iq/app/features/Pages/transactions/Transactions.tsx
index 8bcb8aa..a8629c5 100644
--- a/payment-iq/app/features/Pages/transactions/Transactions.tsx
+++ b/payment-iq/app/features/Pages/transactions/Transactions.tsx
@@ -77,42 +77,41 @@ export default function TransactionTable() {
channel: "",
});
};
-
- const filterRows = (rows1, filters) => {
+
+ const filterRows = (rows1, filters) => {
// debugger
- return rows1.filter(row => {
- const hasTransactionIdFilter = filters.transactionID !== "";
- const hasStateFilter = filters.state !== "";
+ return rows1.filter(row => {
+ const hasTransactionIdFilter = filters.transactionID !== "";
+ const hasStateFilter = filters.state !== "";
- console.log(1111, filters.transactionID, hasTransactionIdFilter)
- if (hasTransactionIdFilter && hasStateFilter) {
- console.log(1234)
- // Return rows that match BOTH filters
- return row.transactionID == filters.transactionID && row.state.toLowerCase() === filters.state.toLowerCase();
- } else if (hasTransactionIdFilter) {
- console.log(12345)
- // Return rows that match merchandId only
- return row.transactionID == filters.transactionID;
- } else if (hasStateFilter) {
- // Return rows that match state only
- console.log(123456)
- return row.state.toLowerCase() === filters.state.toLowerCase();
- } else {
+ if (hasTransactionIdFilter && hasStateFilter) {
+ console.log(1234)
+ // Return rows that match BOTH filters
+ return row.transactionID == filters.transactionID && row.state.toLowerCase() === filters.state.toLowerCase();
+ } else if (hasTransactionIdFilter) {
+ console.log(12345)
+ // Return rows that match merchandId only
+ return row.transactionID == filters.transactionID;
+ } else if (hasStateFilter) {
+ // Return rows that match state only
+ console.log(123456)
+ return row.state.toLowerCase() === filters.state.toLowerCase();
+ } else {
console.log(1234567)
- // No filters applied, return all rows
- return rows;
- }
- });
-};
+ // No filters applied, return all rows
+ return rows;
+ }
+ });
+ };
- useEffect(()=>{
+ useEffect(() => {
console.log(form)
console.log(filterRows(rows, { transactionID: form.transactionID, state: form.state }))
- setFilteredRows(filterRows(rows, { transactionID: form.transactionID, state: form.state }));
- },[form])
+ setFilteredRows(filterRows(rows, { transactionID: form.transactionID, state: form.state }));
+ }, [form])
// useEffect(()=>{
// if(form?.transactionId){
diff --git a/payment-iq/app/layout.tsx b/payment-iq/app/layout.tsx
index 2a6d7a1..142102a 100644
--- a/payment-iq/app/layout.tsx
+++ b/payment-iq/app/layout.tsx
@@ -1,6 +1,8 @@
import ThemeRegistry from "@/config/ThemeRegistry";
import type { Metadata } from "next";
import "../styles/globals.scss";
+import { Providers } from "./providers/providers";
+import { MSWProvider } from './providers/msw-provider';
export const metadata: Metadata = {
title: "Your App",
@@ -15,7 +17,11 @@ export default function RootLayout({
return (
- {children}
+
+
+ {children}
+
+
);
diff --git a/payment-iq/app/providers/msw-provider.tsx b/payment-iq/app/providers/msw-provider.tsx
new file mode 100644
index 0000000..9f3bf55
--- /dev/null
+++ b/payment-iq/app/providers/msw-provider.tsx
@@ -0,0 +1,13 @@
+'use client';
+import { useEffect } from 'react';
+
+export function MSWProvider({ children }: { children: React.ReactNode }) {
+ useEffect(() => {
+ if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') {
+ const { worker } = require('../../mock/browser.ts');
+ worker.start();
+ }
+ }, []);
+
+ return <>{children}>;
+}
diff --git a/payment-iq/app/providers/providers.tsx b/payment-iq/app/providers/providers.tsx
new file mode 100644
index 0000000..ff55a46
--- /dev/null
+++ b/payment-iq/app/providers/providers.tsx
@@ -0,0 +1,10 @@
+'use client';
+
+import { ReactNode } from 'react';
+import { Provider } from 'react-redux';
+import { store } from '../../lib/store';
+
+export function Providers({ children }: { children: ReactNode }) {
+ return {children};
+}
+
diff --git a/payment-iq/app/test/page.tsx b/payment-iq/app/test/page.tsx
new file mode 100644
index 0000000..966a371
--- /dev/null
+++ b/payment-iq/app/test/page.tsx
@@ -0,0 +1,50 @@
+// app/test/page.tsx
+'use client';
+
+import { useEffect, useState } from 'react';
+
+export default function TestPage() {
+ const [user, setUser] = useState(null);
+ const [loginStatus, setLoginStatus] = useState('');
+
+ useEffect(() => {
+ // Test GET request
+ fetch('https://api.example.com/user')
+ .then(res => res.json())
+ .then(data => setUser(data));
+ }, []);
+
+ const handleLogin = async () => {
+ // Test POST request
+ const response = await fetch('https://api.example.com/login', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ username: 'admin',
+ password: 'password123'
+ })
+ });
+
+ const result = await response.json();
+ setLoginStatus(response.ok ? 'Login successful' : `Error: ${result.error}`);
+ };
+
+ return (
+
+
MSW Test Page
+
+
+ User Data (GET)
+ {JSON.stringify(user, null, 2)}
+
+
+
+ Login Test (POST)
+
+ {loginStatus}
+
+
+ );
+}
diff --git a/payment-iq/app/testWithParams/page.tsx b/payment-iq/app/testWithParams/page.tsx
new file mode 100644
index 0000000..71f1def
--- /dev/null
+++ b/payment-iq/app/testWithParams/page.tsx
@@ -0,0 +1,97 @@
+// app/products/page.tsx
+'use client';
+
+import { useState } from 'react';
+
+export default function ProductsPage() {
+ const [category, setCategory] = useState('');
+ const [sort, setSort] = useState('price');
+ const [limit, setLimit] = useState('10');
+ const [products, setProducts] = useState([]);
+ const [loading, setLoading] = useState(false);
+
+ const fetchProducts = async () => {
+ setLoading(true);
+ try {
+ // Construct URL with query parameters
+ const url = new URL('https://api.example.com/products');
+ if (category) url.searchParams.append('category', category);
+ if (sort) url.searchParams.append('sort', sort);
+ if (limit) url.searchParams.append('limit', limit);
+
+ const response = await fetch(url.toString());
+ const data = await response.json();
+ setProducts(data.products);
+ } catch (error) {
+ console.error('Error fetching products:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
Product Search
+
+
+
+
+ setCategory(e.target.value)}
+ className="border p-2 rounded"
+ placeholder="electronics, clothing, etc."
+ />
+
+
+
+
+
+
+
+
+
+ setLimit(e.target.value)}
+ className="border p-2 rounded"
+ min="1"
+ max="100"
+ />
+
+
+
+
+
+ {products.length > 0 && (
+
+
Results
+
+ {products.map((product) => (
+
+
{product.name}
+
Category: {product.category}
+
Price: ${product.price}
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/payment-iq/lib/store.ts b/payment-iq/lib/store.ts
new file mode 100644
index 0000000..812f9b7
--- /dev/null
+++ b/payment-iq/lib/store.ts
@@ -0,0 +1,12 @@
+import { configureStore } from '@reduxjs/toolkit';
+import advancedSearchReducer from '@/app/features/AdvancedSearch/store/advancedSearchSlice';
+
+export const store = configureStore({
+ reducer: {
+ advancedSearch: advancedSearchReducer,
+ },
+});
+
+export type RootState = ReturnType;
+export type AppDispatch = typeof store.dispatch;
+
diff --git a/payment-iq/mock/browser.ts b/payment-iq/mock/browser.ts
index 975f2cd..2845183 100644
--- a/payment-iq/mock/browser.ts
+++ b/payment-iq/mock/browser.ts
@@ -1,5 +1,9 @@
-// mocks/browser.ts
-import { setupWorker } from "msw/browser";
-import { handlers } from "./handlers";
+// // mocks/browser.ts import { setupWorker } from "msw/browser";
+// import { handlers } from "./handlers";
+//
+// export const worker = setupWorker(...handlers);
+
+import { setupWorker } from 'msw/browser';
+import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
diff --git a/payment-iq/mock/handlers.ts b/payment-iq/mock/handlers.ts
index 6db727a..902d618 100644
--- a/payment-iq/mock/handlers.ts
+++ b/payment-iq/mock/handlers.ts
@@ -1,96 +1,98 @@
-import { http, HttpResponse } from "msw";
+// import { http, HttpResponse } from "msw";
+//
+// export const handlers = [
+// http.get(
+// "https://test-bo.paymentiq.io/paymentiq/backoffice/api/v2/metrics/txsummary",
+// (req, _res, _ctx) => {
+// const merchantId = req.url.searchParams.get("merchantId");
+// const fromDate = req.url.searchParams.get("fromDate");
+// const toDate = req.url.searchParams.get("toDate");
+//
+// console.log(merchantId, fromDate, toDate);
+//
+// return HttpResponse.json({
+// result: {
+// txCount: { total: 0, successful: 0 },
+// amount: { value: "0", currency: "EUR" },
+// },
+// });
+// }
+// ),
+// ];
+
+
+import { http, HttpResponse } from 'msw';
export const handlers = [
- http.get(
- "https://test-bo.paymentiq.io/paymentiq/backoffice/api/v2/metrics/txsummary",
- (req, _res, _ctx) => {
- const merchantId = req.url.searchParams.get("merchantId");
- const fromDate = req.url.searchParams.get("fromDate");
- const toDate = req.url.searchParams.get("toDate");
+ // Simple GET endpoint
+ http.get('https://api.example.com/user', () => {
+ return HttpResponse.json({
+ id: 'usr_123',
+ name: 'John Doe',
+ email: 'john@example.com'
+ });
+ }),
- console.log(merchantId, fromDate, toDate);
+ // POST endpoint with request validation
+ http.post('https://api.example.com/login', async ({ request }) => {
+ const { username, password } = await request.json() as { username: string; password: string };
+ if (username === 'admin' && password === 'password123') {
return HttpResponse.json({
- result: {
- txCount: { total: 0, successful: 0 },
- amount: { value: "0", currency: "EUR" },
- },
+ token: 'mock-jwt-token',
+ user: { id: 'usr_123', name: 'Admin User' }
});
}
- ),
- http.get(
- "https://test-bo.paymentiq.io/paymentiq/backoffice/api/v2/users/",
- (req, _res, _ctx) => {
- // Mock data for merchantId = 100987998
- if (true) {
- return HttpResponse.json({
- result: [
- {
- merchantId: 100987998,
- id: "bc6a8a55-13bc-4538-8255-cd0cec3bb4e9",
- username: "lspaddy",
- firstName: "Paddy",
- lastName: "Man",
- email: "patrick@omegasys.eu",
- phone: "",
- jobTitle: "",
- enabled: true,
- authorities: [
- "ROLE_IIN",
- "ROLE_FIRST_APPROVER",
- "ROLE_RULES_ADMIN",
- "ROLE_TRANSACTION_VIEWER",
- "ROLE_IIN_ADMIN",
- "ROLE_USER_PSP_ACCOUNT",
- ],
- allowedMerchantIds: [100987998],
- created: "2025-05-04T15:32:48.432Z",
- disabledBy: null,
- disabledDate: null,
- disabledReason: null,
- incidentNotes: false,
- lastLogin: "",
- lastMandatoryUpdated: "2025-05-04T15:32:48.332Z",
- marketingNewsletter: false,
- releaseNotes: false,
- requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"],
- twoFactorCondition: "required",
- twoFactorCredentials: [],
- },
- {
- merchantId: 100987998,
- id: "382eed15-1e21-41fa-b1f3-0c1adb3af714",
- username: "lsterence",
- firstName: "Terence",
- lastName: "User",
- email: "terence@omegasys.eu",
- phone: "",
- jobTitle: "",
- enabled: true,
- authorities: [
- "ROLE_IIN",
- "ROLE_FIRST_APPROVER",
- "ROLE_RULES_ADMIN",
- ],
- allowedMerchantIds: [100987998],
- created: "2025-05-04T15:32:48.432Z",
- disabledBy: null,
- disabledDate: null,
- disabledReason: null,
- incidentNotes: false,
- lastLogin: "",
- lastMandatoryUpdated: "2025-05-04T15:32:48.332Z",
- marketingNewsletter: false,
- releaseNotes: false,
- requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"],
- twoFactorCondition: "required",
- twoFactorCredentials: [],
- },
- // Add more users if needed
- ],
- total: 4,
- });
- }
+
+ return HttpResponse.json(
+ { error: 'Invalid credentials' },
+ { status: 401 }
+ );
+ }),
+
+
+ // Example with query parameters
+ http.get('https://api.example.com/products', ({ request }) => {
+ // Parse the URL to access query parameters
+ const url = new URL(request.url);
+
+ // Get query parameters
+ const category = url.searchParams.get('category');
+ const sort = url.searchParams.get('sort') || 'price';
+ const page = url.searchParams.get('page') || '1';
+ const limit = url.searchParams.get('limit') || '10';
+
+ // Validate parameters
+ if (limit && parseInt(limit) > 100) {
+ return HttpResponse.json(
+ { error: 'Limit cannot exceed 100' },
+ { status: 400 }
+ );
}
- ),
+
+ // Generate mock response based on parameters
+ const mockProducts = Array.from({ length: parseInt(limit) }, (_, i) => ({
+ id: i + 1,
+ name: `Product ${i + 1}${category ? ` in ${category}` : ''}`,
+ price: Math.floor(Math.random() * 100),
+ category: category || 'general',
+ }));
+
+ console.log(1234, mockProducts)
+
+ // Sort products if sort parameter provided
+ if (sort === 'price') {
+ mockProducts.sort((a, b) => a.price - b.price);
+ } else if (sort === 'name') {
+ mockProducts.sort((a, b) => a.name.localeCompare(b.name));
+ }
+
+ return HttpResponse.json({
+ products: mockProducts,
+ page: parseInt(page),
+ totalPages: 5,
+ itemsPerPage: parseInt(limit),
+ sortBy: sort,
+ });
+ }),
];
diff --git a/payment-iq/mock/server.ts b/payment-iq/mock/server.ts
new file mode 100644
index 0000000..719bd8c
--- /dev/null
+++ b/payment-iq/mock/server.ts
@@ -0,0 +1,5 @@
+// mocks/server.ts
+import { setupServer } from 'msw/node';
+import { handlers } from './handlers';
+
+export const server = setupServer(...handlers);
diff --git a/payment-iq/next.config.ts b/payment-iq/next.config.ts
index e9ffa30..b9172f5 100644
--- a/payment-iq/next.config.ts
+++ b/payment-iq/next.config.ts
@@ -2,6 +2,12 @@ import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
+ webpack: (config) => {
+ if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') {
+ config.resolve.alias['@mswjs/interceptors'] = false;
+ }
+ return config;
+ },
};
export default nextConfig;
diff --git a/payment-iq/package.json b/payment-iq/package.json
index d3f094a..c37bf54 100644
--- a/payment-iq/package.json
+++ b/payment-iq/package.json
@@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
+ "msw-init": "msw init public/ --save",
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
@@ -15,6 +16,7 @@
"@mui/material": "^7.1.2",
"@mui/x-data-grid": "^8.5.2",
"@mui/x-date-pickers": "^8.5.3",
+ "@reduxjs/toolkit": "^2.8.2",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"dayjs": "^1.11.13",
@@ -23,6 +25,7 @@
"react": "^19.0.0",
"react-date-range": "^2.0.1",
"react-dom": "^19.0.0",
+ "react-redux": "^9.2.0",
"recharts": "^2.15.3",
"sass": "^1.89.2",
"xlsx": "^0.18.5"
@@ -34,6 +37,7 @@
"@types/react": "^19",
"@types/react-date-range": "^1.4.10",
"@types/react-dom": "^19",
+ "@types/react-redux": "^7.1.34",
"eslint": "^9",
"eslint-config-next": "15.3.3",
"msw": "^2.10.2",
@@ -44,4 +48,4 @@
"public"
]
}
-}
\ No newline at end of file
+}
diff --git a/payment-iq/yarn.lock b/payment-iq/yarn.lock
index cc739b9..2400af5 100644
--- a/payment-iq/yarn.lock
+++ b/payment-iq/yarn.lock
@@ -47,7 +47,7 @@
dependencies:
"@babel/types" "^7.27.3"
-"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0", "@babel/runtime@^7.27.1", "@babel/runtime@^7.27.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
+"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0", "@babel/runtime@^7.27.1", "@babel/runtime@^7.27.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.27.6"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz"
integrity sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==
@@ -850,6 +850,18 @@
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
+"@reduxjs/toolkit@^2.8.2":
+ version "2.8.2"
+ resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.8.2.tgz#f4e9f973c6fc930c1e0f3bf462cc95210c28f5f9"
+ integrity sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==
+ dependencies:
+ "@standard-schema/spec" "^1.0.0"
+ "@standard-schema/utils" "^0.3.0"
+ immer "^10.0.3"
+ redux "^5.0.1"
+ redux-thunk "^3.1.0"
+ reselect "^5.1.0"
+
"@rtsao/scc@^1.1.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz"
@@ -860,6 +872,16 @@
resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.11.0.tgz"
integrity sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==
+"@standard-schema/spec@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c"
+ integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==
+
+"@standard-schema/utils@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@standard-schema/utils/-/utils-0.3.0.tgz#3d5e608f16c2390c10528e98e59aef6bf73cae7b"
+ integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==
+
"@swc/counter@0.1.3":
version "0.1.3"
resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz"
@@ -945,6 +967,14 @@
resolved "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz"
integrity sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==
+"@types/hoist-non-react-statics@^3.3.0":
+ version "3.3.6"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz#6bba74383cdab98e8db4e20ce5b4a6b98caed010"
+ integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
"@types/json-schema@^7.0.15":
version "7.0.15"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
@@ -985,6 +1015,16 @@
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz"
integrity sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==
+"@types/react-redux@^7.1.34":
+ version "7.1.34"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.34.tgz#83613e1957c481521e6776beeac4fd506d11bd0e"
+ integrity sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.0"
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+ redux "^4.0.0"
+
"@types/react-transition-group@^4.4.12":
version "4.4.12"
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
@@ -1007,6 +1047,11 @@
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304"
integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==
+"@types/use-sync-external-store@^0.0.6":
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc"
+ integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==
+
"@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
version "8.34.1"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.1.tgz"
@@ -2420,7 +2465,7 @@ headers-polyfill@^4.0.2:
resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07"
integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==
-hoist-non-react-statics@^3.3.1:
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -2437,6 +2482,11 @@ ignore@^7.0.0:
resolved "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz"
integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==
+immer@^10.0.3:
+ version "10.1.1"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-10.1.1.tgz#206f344ea372d8ea176891545ee53ccc062db7bc"
+ integrity sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==
+
immutable@^5.0.2:
version "5.1.3"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.3.tgz#e6486694c8b76c37c063cca92399fa64098634d4"
@@ -3174,6 +3224,14 @@ react-list@^0.8.13:
resolved "https://registry.npmjs.org/react-list/-/react-list-0.8.18.tgz"
integrity sha512-1OSdDvzuKuwDJvQNuhXxxL+jTmmdtKg1i6KtYgxI9XR98kbOql1FcSGP+Lcvo91fk3cYng+Z6YkC6X9HRJwxfw==
+react-redux@^9.2.0:
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.2.0.tgz#96c3ab23fb9a3af2cb4654be4b51c989e32366f5"
+ integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==
+ dependencies:
+ "@types/use-sync-external-store" "^0.0.6"
+ use-sync-external-store "^1.4.0"
+
react-smooth@^4.0.4:
version "4.0.4"
resolved "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz"
@@ -3224,6 +3282,23 @@ recharts@^2.15.3:
tiny-invariant "^1.3.1"
victory-vendor "^36.6.8"
+redux-thunk@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-3.1.0.tgz#94aa6e04977c30e14e892eae84978c1af6058ff3"
+ integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==
+
+redux@^4.0.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
+ integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+
+redux@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b"
+ integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
+
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
version "1.0.10"
resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz"
@@ -3260,7 +3335,7 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
-reselect@^5.1.1:
+reselect@^5.1.0, reselect@^5.1.1:
version "5.1.1"
resolved "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz"
integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
@@ -3832,7 +3907,7 @@ url-parse@^1.5.3:
querystringify "^2.1.1"
requires-port "^1.0.0"
-use-sync-external-store@^1.5.0:
+use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0:
version "1.5.0"
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz"
integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==