Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proof of concept react query #6417

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module.exports = {
"plugin:react-native-a11y/all",
"plugin:sonarjs/recommended",
"prettier",
"@react-native"
"@react-native",
"plugin:@tanstack/query/recommended"
],
parser: "@typescript-eslint/parser",
parserOptions: {
Expand Down Expand Up @@ -124,24 +125,27 @@ module.exports = {
"no-restricted-imports": [
"error",
{
"paths": [
paths: [
{
name: "i18n-js",
message: 'Importing I18n from "i18n-js" is not allowed. Import it from "ts/i18n.ts" instead.',
},
message:
'Importing I18n from "i18n-js" is not allowed. Import it from "ts/i18n.ts" instead.'
},
{
name: "@pagopa/ts-commons",
importNames: ["pot"],
message: 'Importing { pot } from "@pagopa/ts-commons" is not allowed. Use \'import * as pot from "@pagopa/ts-commons/lib/pot"\' instead.',
message:
'Importing { pot } from "@pagopa/ts-commons" is not allowed. Use \'import * as pot from "@pagopa/ts-commons/lib/pot"\' instead.'
}
],
patterns: [
{
group: ["**/config"],
importNames: ["privacyUrl"],
message: 'Importing "privacyUrl" from "config.ts" module is restricted. Please use "tosConfigSelector" to obtain it instead.'
message:
'Importing "privacyUrl" from "config.ts" module is restricted. Please use "tosConfigSelector" to obtain it instead.'
}
]
]
}
]
},
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ __pycache__

# Auto generated definitions
definitions
fetch-sdk

# Certificates
**/*.p12
Expand Down
91 changes: 91 additions & 0 deletions kubb.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { UserConfig, defineConfig } from "@kubb/core";
import { pluginOas } from "@kubb/plugin-oas";
import { pluginReactQuery } from "@kubb/plugin-react-query";
import { pluginTs } from "@kubb/plugin-ts";
import { pluginZod } from "@kubb/plugin-zod";
import packageJson from "./package.json";

function singleFileApiDefinition({
scope,
schema,
baseURL
}: {
scope: string;
schema: string;
baseURL: string;
}): UserConfig {
return {
input: {
path: schema
},
output: {
path: `./fetch-sdk/${scope}`
},
plugins: [
pluginOas({}),
pluginTs({
unknownType: "unknown",
transformers: {
name(name) {
return `${capitalize(scope)}${name}`;
}
}
}),
pluginZod({
typed: true,
inferred: true,
transformers: {
name(name) {
return `${capitalize(scope)}${capitalize(name)}`;
}
}
}),
pluginReactQuery({
parser: "zod",
query: {
methods: ["get", "post", "put", "delete"]
},
mutation: {
methods: []
},
suspense: false,
// pathParamsType: "object",
// paramsType: "object",
client: {
importPath: "../../../ts/fetch-client.ts",
baseURL,
dataReturnType: "data"
},
transformers: {
name(name, type) {
if (name.startsWith("use")) {
return `use${capitalize(scope)}${name.slice(3)}`;
}
if (type === "file" || type === "function") {
return `${scope}${capitalize(name)}`;
}
return `${capitalize(scope)}${capitalize(name)}`;
}
}
})
]
};
}

export default defineConfig([
singleFileApiDefinition({
scope: "cgn",
schema: (packageJson as any).io_cgn_specs,
baseURL: "/api/v1/cgn"
}),
singleFileApiDefinition({
scope: "cgnMerchants",
schema: (packageJson as any).io_cgn_merchants_specs,
baseURL: "/api/v1/cgn/operator-search"
})
// TODO: list all definitions to generate
]);

function capitalize(text: string) {
return text.charAt(0).toUpperCase() + text.slice(1);
}
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"cie-ios:prod": "mv node_modules/@pagopa/react-native-cie/.ios node_modules/@pagopa/react-native-cie/ios && mv node_modules/@pagopa/react-native-cie/.react-native-cie.podspec node_modules/@pagopa/react-native-cie/react-native-cie.podspec && cd ios && bundle exec pod install",
"cie-ios:dev": "mv node_modules/@pagopa/react-native-cie/ios node_modules/@pagopa/react-native-cie/.ios && mv node_modules/@pagopa/react-native-cie/react-native-cie.podspec node_modules/@pagopa/react-native-cie/.react-native-cie.podspec && cd ios && rm -rf Pods && bundle exec pod install",
"cie-ios:ci": "mv node_modules/@pagopa/react-native-cie/.ios node_modules/@pagopa/react-native-cie/ios && mv node_modules/@pagopa/react-native-cie/.react-native-cie.podspec node_modules/@pagopa/react-native-cie/react-native-cie.podspec",
"generate:kubb": "rimraf fetch-sdk && kubb generate",
"generate:content-definitions": "rimraf definitions/content && mkdir -p definitions/content && gen-api-models --api-spec $npm_package_io_content_specs --out-dir ./definitions/content",
"generate:pagopa-api-definitions": "rimraf definitions/pagopa && mkdir -p definitions/pagopa && gen-api-models --api-spec $npm_package_pagopa_api --out-dir ./definitions/pagopa --no-strict --request-types --response-decoders --default-error-type undefined",
"generate:mock-google-services-json": "cp mock-google-services.json ./android/app/google-services.json",
Expand Down Expand Up @@ -110,6 +111,13 @@
"dependencies": {
"@babel/plugin-transform-regenerator": "^7.18.6",
"@gorhom/bottom-sheet": "^4.1.5",
"@kubb/cli": "^3.0.9",
"@kubb/core": "^3.0.9",
"@kubb/plugin-client": "^3.0.9",
"@kubb/plugin-oas": "^3.0.9",
"@kubb/plugin-react-query": "^3.0.9",
"@kubb/plugin-ts": "^3.0.9",
"@kubb/plugin-zod": "^3.0.9",
"@pagopa/io-app-design-system": "3.0.1",
"@pagopa/io-pagopa-commons": "^3.1.0",
"@pagopa/io-react-native-cieid": "^0.3.5",
Expand Down Expand Up @@ -137,6 +145,7 @@
"@sentry/react-native": "^5.32.0",
"@shopify/flash-list": "~1.7.0",
"@shopify/react-native-skia": "^1.3.13",
"@tanstack/react-query": "^5.60.5",
"@textlint/markdown-to-ast": "^14.0.4",
"@xstate/react": "^4.0.1",
"async-mutex": "^0.1.3",
Expand Down Expand Up @@ -209,6 +218,7 @@
"react-native-xml2js": "^1.0.3",
"react-redux": "8.1.3",
"reactotron-react-native": "^5.0.0",
"reactotron-react-query": "^1.0.4",
"reactotron-redux": "^3.1.3",
"reactotron-redux-saga": "4.2.3",
"redux": "4.1.1",
Expand Down Expand Up @@ -248,6 +258,7 @@
"@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.12",
"@stylistic/eslint-plugin-js": "^2.1.0",
"@tanstack/eslint-plugin-query": "^5.60.1",
"@testing-library/jest-native": "^3.4.3",
"@testing-library/react-native": "^8.0.0",
"@tsconfig/react-native": "^3.0.0",
Expand Down Expand Up @@ -310,6 +321,7 @@
"react-native-bundle-visualizer": "^2.2.1",
"react-native-get-random-values": "^1.11.0",
"react-native-svg-transformer": "^0.14.3",
"react-query-native-devtools": "^4.0.0",
"react-test-renderer": "18.2.0",
"redux-mock-store": "^1.5.4",
"redux-saga-test-plan": "4.0.3",
Expand Down
25 changes: 14 additions & 11 deletions ts/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { LightModalProvider } from "./components/ui/LightModal";
import { sentryDsn } from "./config";
import { isDevEnv } from "./utils/environment";
import { StatusMessages } from "./components/StatusMessages";
import { ReactQueryProvider } from "./react-query";

export const routingInstrumentation = Sentry.reactNavigationIntegration({
enableTimeToInitialDisplay: true
Expand Down Expand Up @@ -68,17 +69,19 @@ const App = (): JSX.Element => (
<IOThemeContextProvider theme={"light"}>
<ToastProvider>
<Provider store={store}>
<PersistGate loading={undefined} persistor={persistor}>
<BottomSheetModalProvider>
<LightModalProvider>
<StatusMessages>
<RootContainer
routingInstumentation={routingInstrumentation}
/>
</StatusMessages>
</LightModalProvider>
</BottomSheetModalProvider>
</PersistGate>
<ReactQueryProvider>
<PersistGate loading={undefined} persistor={persistor}>
<BottomSheetModalProvider>
<LightModalProvider>
<StatusMessages>
<RootContainer
routingInstumentation={routingInstrumentation}
/>
</StatusMessages>
</LightModalProvider>
</BottomSheetModalProvider>
</PersistGate>
</ReactQueryProvider>
</Provider>
</ToastProvider>
</IOThemeContextProvider>
Expand Down
9 changes: 0 additions & 9 deletions ts/features/bonus/cgn/saga/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
cgnEycaActivationStatusRequest
} from "../store/actions/eyca/activation";
import {
cgnMerchantsCount,
cgnOfflineMerchants,
cgnOnlineMerchants,
cgnSearchMerchants,
Expand All @@ -40,7 +39,6 @@ import { cgnMerchantDetail } from "./networking/merchants/cgnMerchantDetail";
import { cgnOfflineMerchantsSaga } from "./networking/merchants/cgnOfflineMerchantsSaga";
import { cgnOnlineMerchantsSaga } from "./networking/merchants/cgnOnlineMerchantsSaga";
import { cgnSearchMerchantsSaga } from "./networking/merchants/cgnSearchMerchantsSaga";
import { cgnGetMerchantsCountSaga } from "./networking/merchants/cgnGetMerchantsCountSaga";
import { cgnBucketConsuption } from "./networking/bucket";
import { cgnUnsubscriptionHandler } from "./networking/unsubscribe";
import { cgnCategoriesSaga } from "./networking/categories/cgnCategoriesSaga";
Expand Down Expand Up @@ -112,13 +110,6 @@ export function* watchBonusCgnSaga(bearerToken: string): SagaIterator {
backendCgnMerchants.getPublishedCategories
);

// CGN Merchants count
yield* takeLatest(
getType(cgnMerchantsCount.request),
cgnGetMerchantsCountSaga,
backendCgnMerchants.getMerchantsCount
);

// CGN Search Merchants
yield* takeLatest(
getType(cgnSearchMerchants.request),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,17 @@ import {
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useFocusEffect } from "@react-navigation/native";
import { NonEmptyString } from "@pagopa/ts-commons/lib/strings";
import { useQuery } from "@tanstack/react-query";
import I18n from "../../../../../i18n";
import { useIONavigation } from "../../../../../navigation/params/AppParamsList";
import { useDebouncedValue } from "../../../../../hooks/useDebouncedValue";
import { useIODispatch, useIOSelector } from "../../../../../store/hooks";
import {
cgnMerchantsCountSelector,
cgnSearchMerchantsSelector
} from "../../store/reducers/merchants";
import { cgnSearchMerchantsSelector } from "../../store/reducers/merchants";
import { getValue } from "../../../../../common/model/RemoteValue";
import { SearchItem } from "../../../../../../definitions/cgn/merchants/SearchItem";
import {
cgnMerchantsCount,
cgnSearchMerchants
} from "../../store/actions/merchants";
import { cgnSearchMerchants } from "../../store/actions/merchants";
import { MerchantSearchResultListItem } from "../../components/merchants/MerchantSearchResultListItem";
import { cgnMerchantsCountQueryOptions } from "../../../../../../fetch-sdk/cgnMerchants";

const INPUT_PADDING: IOSpacingScale = 16;
const MIN_SEARCH_TEXT_LENGTH: number = 3;
Expand Down Expand Up @@ -94,11 +90,8 @@ export function CgnMerchantSearchScreen() {
[searchTextDebouncedTrimmed]
);

const merchantsCountRemoteValue = useIOSelector(cgnMerchantsCountSelector);
useEffect(() => {
dispatch(cgnMerchantsCount.request());
}, [dispatch]);
const merchantsCount = getValue(merchantsCountRemoteValue);
const merchantsCountQuery = useQuery(cgnMerchantsCountQueryOptions());
const merchantsCount = merchantsCountQuery.data?.count;

const renderListEmptyComponent = useCallback(() => {
if (searchText.trim().length < MIN_SEARCH_TEXT_LENGTH) {
Expand Down
11 changes: 0 additions & 11 deletions ts/features/bonus/cgn/store/actions/merchants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@ import { SearchRequest } from "../../../../../../definitions/cgn/merchants/Searc
import { OfflineMerchantSearchRequest } from "../../../../../../definitions/cgn/merchants/OfflineMerchantSearchRequest";
import { OnlineMerchantSearchRequest } from "../../../../../../definitions/cgn/merchants/OnlineMerchantSearchRequest";
import { Discount } from "../../../../../../definitions/cgn/merchants/Discount";
import { CountResult } from "../../../../../../definitions/cgn/merchants/CountResult";

/**
* count merchants conventioned with CGN
*/
export const cgnMerchantsCount = createAsyncAction(
"CGN_MERCHANTS_COUNT_REQUEST",
"CGN_MERCHANTS_COUNT_SUCCESS",
"CGN_MERCHANTS_COUNT_FAILURE"
)<void, CountResult, NetworkError>();

/**
* search merchants conventioned with CGN
Expand Down Expand Up @@ -69,7 +59,6 @@ export const resetMerchantDiscountCode = createStandardAction(
)<void>();

export type CgnMerchantsAction =
| ActionType<typeof cgnMerchantsCount>
| ActionType<typeof cgnSearchMerchants>
| ActionType<typeof cgnOfflineMerchants>
| ActionType<typeof cgnOnlineMerchants>
Expand Down
Loading
Loading