Fix @probo/trust lint errors
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
import js from '@eslint/js'
|
||||
import globals from 'globals'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import tseslint from 'typescript-eslint'
|
||||
|
||||
export default tseslint.config(
|
||||
{ ignores: ['dist'] },
|
||||
{
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
},
|
||||
plugins: {
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
},
|
||||
rules: {
|
||||
...reactHooks.configs.recommended.rules,
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
27
apps/trust/eslint.config.mjs
Normal file
27
apps/trust/eslint.config.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
// @ts-check
|
||||
|
||||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import reactHooks from "eslint-plugin-react-hooks";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default tseslint.config(
|
||||
{ ignores: ["dist"] },
|
||||
{
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||
files: ["**/*.{ts,tsx}"],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
parserOptions: {
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
"react-hooks": reactHooks,
|
||||
},
|
||||
rules: {
|
||||
...reactHooks.configs.recommended.rules,
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -16,6 +16,7 @@
|
||||
"@probo/helpers": "1.0.0",
|
||||
"@probo/hooks": "1.0.0",
|
||||
"@probo/i18n": "1.0.0",
|
||||
"@probo/routes": "^1.0.0",
|
||||
"@probo/ui": "1.0.0",
|
||||
"clsx": "^2.1.1",
|
||||
"react": "^19.1.0",
|
||||
@@ -41,7 +42,6 @@
|
||||
"babel-plugin-relay": "^19.0.0",
|
||||
"eslint": "^9.25.0",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.19",
|
||||
"globals": "^16.0.0",
|
||||
"graphql": "^16.11.0",
|
||||
"prettier": "^3.5.3",
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* Hook to handle cleanup after a delay
|
||||
*
|
||||
* Used for disposing the graphQL query when the component unmounts
|
||||
*/
|
||||
export function useCleanup(callback: () => void, delay: number) {
|
||||
const timer = useRef<ReturnType<typeof setTimeout>>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (timer.current) {
|
||||
clearTimeout(timer.current);
|
||||
}
|
||||
return () => {
|
||||
timer.current = setTimeout(callback, delay);
|
||||
};
|
||||
}, [callback, delay]);
|
||||
}
|
||||
@@ -56,7 +56,7 @@ export function useMutationWithToasts<T extends MutationParameters>(
|
||||
})
|
||||
);
|
||||
},
|
||||
[mutate]
|
||||
[mutate, toast, __, baseOptions]
|
||||
);
|
||||
|
||||
return [mutateWithToast, isLoading] as const;
|
||||
|
||||
@@ -175,7 +175,7 @@ function Subprocessors({
|
||||
}
|
||||
|
||||
const hasAnyCountries = vendors.some((vendor) => {
|
||||
const vendorData = vendor.node as any;
|
||||
const vendorData = vendor.node;
|
||||
return vendorData.countries && vendorData.countries.length > 0;
|
||||
});
|
||||
|
||||
|
||||
@@ -2,18 +2,15 @@ import {
|
||||
createBrowserRouter,
|
||||
Navigate,
|
||||
redirect,
|
||||
type RouteObject,
|
||||
useLoaderData,
|
||||
useRouteError,
|
||||
} from "react-router";
|
||||
import { type ComponentType, Fragment, Suspense } from "react";
|
||||
import { Fragment } from "react";
|
||||
import {
|
||||
relayEnvironment,
|
||||
UnAuthenticatedError,
|
||||
} from "./providers/RelayProviders";
|
||||
import { loadQuery, type PreloadedQuery } from "react-relay";
|
||||
import { useCleanup } from "./hooks/useDelayedEffect";
|
||||
import { PageError } from "./components/PageError";
|
||||
} from "./providers/RelayProviders.tsx";
|
||||
import { loadQuery } from "react-relay";
|
||||
import { PageError } from "./components/PageError.tsx";
|
||||
import { MainLayout } from "/layouts/MainLayout";
|
||||
import {
|
||||
currentTrustGraphQuery,
|
||||
@@ -24,15 +21,9 @@ import { OverviewPage } from "/pages/OverviewPage";
|
||||
import { DocumentsPage } from "/pages/DocumentsPage";
|
||||
import { SubprocessorsPage } from "/pages/SubprocessorsPage";
|
||||
import { AccessPage } from "./pages/AccessPage.tsx";
|
||||
import { TabSkeleton } from "./components/Skeletons/TabSkeleton";
|
||||
import { MainSkeleton } from "./components/Skeletons/MainSkeleton";
|
||||
|
||||
export type AppRoute = Omit<RouteObject, "Component" | "children"> & {
|
||||
Component?: ComponentType<any>;
|
||||
children?: AppRoute[];
|
||||
fallback?: ComponentType;
|
||||
queryLoader?: (params: any) => PreloadedQuery<any>;
|
||||
};
|
||||
import { TabSkeleton } from "./components/Skeletons/TabSkeleton.tsx";
|
||||
import { MainSkeleton } from "./components/Skeletons/MainSkeleton.tsx";
|
||||
import { loaderFromQueryLoader, routeFromAppRoute, withQueryRef, type AppRoute } from "@probo/routes";
|
||||
|
||||
/**
|
||||
* Top level error boundary
|
||||
@@ -59,47 +50,45 @@ const routes = [
|
||||
// Custom domain routes (subdomain-based)
|
||||
{
|
||||
path: "/overview",
|
||||
queryLoader: () => loadQuery(relayEnvironment, currentTrustGraphQuery, {}),
|
||||
Component: MainLayout,
|
||||
fallback: MainSkeleton,
|
||||
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustGraphQuery, {})),
|
||||
Component: withQueryRef(MainLayout),
|
||||
Fallback: MainSkeleton,
|
||||
ErrorBoundary: ErrorBoundary,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
fallback: TabSkeleton,
|
||||
Fallback: TabSkeleton,
|
||||
Component: OverviewPage,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/documents",
|
||||
queryLoader: () => loadQuery(relayEnvironment, currentTrustGraphQuery, {}),
|
||||
Component: MainLayout,
|
||||
fallback: MainSkeleton,
|
||||
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustGraphQuery, {})),
|
||||
Component: withQueryRef(MainLayout),
|
||||
Fallback: MainSkeleton,
|
||||
ErrorBoundary: ErrorBoundary,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
queryLoader: () =>
|
||||
loadQuery(relayEnvironment, currentTrustDocumentsQuery, {}),
|
||||
fallback: TabSkeleton,
|
||||
Component: DocumentsPage,
|
||||
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustDocumentsQuery, {})),
|
||||
Fallback: TabSkeleton,
|
||||
Component: withQueryRef(DocumentsPage),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/subprocessors",
|
||||
queryLoader: () => loadQuery(relayEnvironment, currentTrustGraphQuery, {}),
|
||||
Component: MainLayout,
|
||||
fallback: MainSkeleton,
|
||||
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustGraphQuery, {})),
|
||||
Component: withQueryRef(MainLayout),
|
||||
Fallback: MainSkeleton,
|
||||
ErrorBoundary: ErrorBoundary,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
queryLoader: () =>
|
||||
loadQuery(relayEnvironment, currentTrustVendorsQuery, {}),
|
||||
fallback: TabSkeleton,
|
||||
Component: SubprocessorsPage,
|
||||
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustVendorsQuery, {})),
|
||||
Fallback: TabSkeleton,
|
||||
Component: withQueryRef(SubprocessorsPage),
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -115,56 +104,6 @@ const routes = [
|
||||
},
|
||||
] satisfies AppRoute[];
|
||||
|
||||
/**
|
||||
* Wrap components with suspense to handle lazy loading & relay loading states
|
||||
*/
|
||||
function routeTransformer({
|
||||
fallback: FallbackComponent,
|
||||
queryLoader,
|
||||
...route
|
||||
}: AppRoute): RouteObject {
|
||||
let result = { ...route };
|
||||
if (FallbackComponent && route.Component) {
|
||||
const OriginalComponent = route.Component;
|
||||
result = {
|
||||
...result,
|
||||
Component: (props) => (
|
||||
<Suspense fallback={<FallbackComponent />}>
|
||||
<OriginalComponent {...props} />
|
||||
</Suspense>
|
||||
),
|
||||
};
|
||||
}
|
||||
if (queryLoader && route.Component) {
|
||||
const OriginalComponent = route.Component;
|
||||
result = {
|
||||
...result,
|
||||
loader: ({ params }) => {
|
||||
const query = queryLoader(params as Record<string, string>);
|
||||
return {
|
||||
queryRef: query,
|
||||
dispose: query.dispose,
|
||||
};
|
||||
},
|
||||
Component: () => {
|
||||
const { queryRef, dispose } = useLoaderData();
|
||||
|
||||
useCleanup(dispose, 1000);
|
||||
|
||||
return (
|
||||
<Suspense fallback={FallbackComponent ? <FallbackComponent /> : null}>
|
||||
<OriginalComponent queryRef={queryRef} />
|
||||
</Suspense>
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
...result,
|
||||
children: route.children?.map(routeTransformer),
|
||||
} as RouteObject;
|
||||
}
|
||||
|
||||
// Detect basename from current URL path
|
||||
// If URL starts with /trust/{slug}, extract that as the basename
|
||||
// Otherwise, use "/" for custom domains
|
||||
@@ -174,6 +113,6 @@ function getBasename(): string {
|
||||
return trustMatch ? trustMatch[0] : "/";
|
||||
}
|
||||
|
||||
export const router = createBrowserRouter(routes.map(routeTransformer), {
|
||||
export const router = createBrowserRouter(routes.map(routeFromAppRoute), {
|
||||
basename: getBasename(),
|
||||
});
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -22,10 +22,11 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@probo/helpers": "1.0.0",
|
||||
"@probo/helpers": "^1.0.0",
|
||||
"@probo/hooks": "1.0.0",
|
||||
"@probo/i18n": "1.0.0",
|
||||
"@probo/react-lazy": "1.0.0",
|
||||
"@probo/routes": "^1.0.0",
|
||||
"@probo/ui": "1.0.0",
|
||||
"@probo/vendors": "0.0.1",
|
||||
"@tanstack/react-query": "^5.76.1",
|
||||
@@ -72,6 +73,7 @@
|
||||
"@probo/helpers": "1.0.0",
|
||||
"@probo/hooks": "1.0.0",
|
||||
"@probo/i18n": "1.0.0",
|
||||
"@probo/routes": "^1.0.0",
|
||||
"@probo/ui": "1.0.0",
|
||||
"clsx": "^2.1.1",
|
||||
"react": "^19.1.0",
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { ComponentType, LazyExoticComponent } from "react";
|
||||
import { EnvironmentProviderOptions, PreloadedQuery } from "react-relay";
|
||||
import { LoaderFunction, LoaderFunctionArgs, RouteObject, useLoaderData } from "react-router";
|
||||
import { OperationType } from "relay-runtime";
|
||||
import { useCleanup } from "./useDelayedEffect";
|
||||
|
||||
export function withQueryRef<
|
||||
TQuery extends OperationType,
|
||||
TEnvironmentProviderOptions = EnvironmentProviderOptions
|
||||
>(
|
||||
Component: LazyExoticComponent<ComponentType<{ queryRef: PreloadedQuery<TQuery, TEnvironmentProviderOptions> }>>,
|
||||
) {
|
||||
return () => {
|
||||
const { queryRef, dispose } = useLoaderData();
|
||||
|
||||
useCleanup(dispose, 1000);
|
||||
|
||||
return <Component queryRef={queryRef} />
|
||||
}
|
||||
}
|
||||
|
||||
export function loaderFromQueryLoader<
|
||||
TQuery extends OperationType,
|
||||
TEnvironmentProviderOptions = EnvironmentProviderOptions
|
||||
>(
|
||||
queryLoader: (params: Record<string, string>) => PreloadedQuery<TQuery, TEnvironmentProviderOptions>
|
||||
): LoaderFunction {
|
||||
return ({ params }: LoaderFunctionArgs) => {
|
||||
const query = queryLoader(params as Record<string, string>);
|
||||
return {
|
||||
queryRef: query,
|
||||
dispose: query.dispose,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export type AppRoute = Omit<RouteObject, "children"> & {
|
||||
children?: AppRoute[];
|
||||
fallback?: ComponentType;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* Hook to handle cleanup after a delay
|
||||
*
|
||||
* Used for disposing the graphQL query when the component unmounts
|
||||
*/
|
||||
export function useCleanup(callback: () => void, delay: number) {
|
||||
const timer = useRef<ReturnType<typeof setTimeout>>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (timer.current) {
|
||||
clearTimeout(timer.current);
|
||||
}
|
||||
return () => {
|
||||
timer.current = setTimeout(callback, delay);
|
||||
};
|
||||
}, [callback, delay]);
|
||||
}
|
||||
@@ -3,3 +3,4 @@ export { useToggle } from "./useToggle";
|
||||
export { useRefSync } from "./useRefSync";
|
||||
export { useList } from "./useList";
|
||||
export { useStateWithRef } from "./useStateWithRef";
|
||||
export { useCleanup } from "./useCleanup";
|
||||
|
||||
Reference in New Issue
Block a user