@accounter/client 0.0.8-alpha-20251022130946-0923a77d2ee3f22a60a7f5b1e0623bd3bee88868 → 0.0.8-alpha-20251022132023-9f41aae2ce16f8761101edc548f486cc6ce80333
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/CHANGELOG.md +25 -1
- package/dist/assets/Checkbox-DBF5r7jA.js +6 -0
- package/dist/assets/Progress-Cjv9yrat.js +1 -0
- package/dist/assets/Typography-DdVppmQe.js +1 -0
- package/dist/assets/accordion-DcMd-Til.js +1 -0
- package/dist/assets/accountant-approvals-CU_EA64d.js +1 -0
- package/dist/assets/all-charges-DKGmrDeD.js +1 -0
- package/dist/assets/arrow-up-down-BeIaAKWn.js +6 -0
- package/dist/assets/business-EtSaFzKh.js +37 -0
- package/dist/assets/business-transactions-single-B0Up2Bs4.js +1 -0
- package/dist/assets/business-trip-CmMmdjCh.js +1 -0
- package/dist/assets/charges-filters-CqWjSIKI.js +1 -0
- package/dist/assets/charges-ledger-validation-DHfLjNlq.js +1 -0
- package/dist/assets/chart-D1Y6fN3z.js +74 -0
- package/dist/assets/data-table-pagination-BCciANKD.js +11 -0
- package/dist/assets/editable-business-trip-VNJjiYOp.js +16 -0
- package/dist/assets/graphql-document-dedupe-fragments-ByT8-wlV.js +1 -0
- package/dist/assets/index-1L3dEkVN.js +1 -0
- package/dist/assets/index-4ZIYAzBJ.js +1 -0
- package/dist/assets/index-4r9JDo8p.js +1 -0
- package/dist/assets/index-BFHiMLVc.js +1 -0
- package/dist/assets/index-BGmhxff9.js +1 -0
- package/dist/assets/index-BMcyYDGt.js +11 -0
- package/dist/assets/index-BVQkLk5i.js +1 -0
- package/dist/assets/index-Bj3HckU6.js +876 -0
- package/dist/assets/index-BnQW4CTb.js +1 -0
- package/dist/assets/index-C0FVazZA.js +24 -0
- package/dist/assets/index-CUDeasQ_.js +1 -0
- package/dist/assets/index-Cfm6e2hX.js +1 -0
- package/dist/assets/index-Cqz-mRoO.js +17 -0
- package/dist/assets/index-Cs7MeC4J.js +137 -0
- package/dist/assets/index-CzzfC-dD.css +1 -0
- package/dist/assets/index-DABsOOfA.js +1 -0
- package/dist/assets/index-DB4BgQdp.js +2 -0
- package/dist/assets/index-DV-Q6DUw.js +1 -0
- package/dist/assets/index-Dd5ylSyH.js +9 -0
- package/dist/assets/index-Dn7p3J8Q.js +1 -0
- package/dist/assets/index-Dpk6i3ex.js +6 -0
- package/dist/assets/index-EiT4SOpW.js +2 -0
- package/dist/assets/index-rcKvu7eR.js +6 -0
- package/dist/assets/index-sDbz8nnb.js +1 -0
- package/dist/assets/{index.es-CWwhWGxX.js → index.es-CL8po8bM.js} +5 -5
- package/dist/assets/issue-document-CYdlZijI.js +1 -0
- package/dist/assets/login-page-CnMdssTN.js +1 -0
- package/dist/assets/missing-info-charges-CzeKbCyG.js +1 -0
- package/dist/assets/page-not-found-Bsa0DCM4.js +1 -0
- package/dist/assets/pencil-BMWYIsZB.js +6 -0
- package/dist/assets/report-commentary-row-D9AtKtZx.js +1 -0
- package/dist/assets/save-DC_eQcBj.js +11 -0
- package/dist/assets/sequential-CAnleQny.js +1 -0
- package/dist/assets/similar-charges-by-business-modal-Dmb2ZymF.js +1 -0
- package/dist/assets/sub-BIMwxqar.js +1 -0
- package/dist/assets/subMonths-B7SR4Lli.js +1 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/components/business-transactions/business-extended-info.tsx +13 -15
- package/src/components/business-transactions/business-transactions-single.tsx +3 -3
- package/src/components/business-transactions/index.tsx +12 -1
- package/src/components/business-trips/business-trip.tsx +3 -3
- package/src/components/charges/cells/business-trip.tsx +6 -8
- package/src/components/charges/cells/counterparty.tsx +7 -5
- package/src/components/common/accounter-table.tsx +6 -5
- package/src/components/common/business-trip-report/parts/core-expense-row.tsx +11 -9
- package/src/components/common/business-trip-report/parts/uncategorized-transactions.tsx +11 -13
- package/src/components/common/buttons/index.ts +0 -2
- package/src/components/common/buttons/logout-button.tsx +7 -6
- package/src/components/common/documents-to-charge-matcher/selection-handler/index.tsx +4 -2
- package/src/components/common/documents-to-charge-matcher/selection-handler/wide-filtered-selection.tsx +5 -7
- package/src/components/common/forms/edit-document.tsx +21 -10
- package/src/components/common/new-documents-list.tsx +10 -8
- package/src/components/documents-table/cells/creditor.tsx +11 -4
- package/src/components/documents-table/cells/debtor.tsx +11 -4
- package/src/components/error-boundary.tsx +189 -0
- package/src/components/layout/breadcrumbs.tsx +72 -0
- package/src/components/layout/dashboard-layout.tsx +4 -0
- package/src/components/layout/document-title.tsx +26 -0
- package/src/components/layout/navigation-progress.tsx +52 -0
- package/src/components/layout/page-skeleton.tsx +49 -0
- package/src/components/layout/sidelinks.tsx +28 -27
- package/src/components/ledger-table/counterparty-cell.tsx +19 -13
- package/src/components/login-page.tsx +2 -1
- package/src/components/reports/corporate-tax-ruling-compliance-report/index.tsx +3 -3
- package/src/components/reports/profit-and-loss-report/index.tsx +3 -3
- package/src/components/reports/tax-report/index.tsx +3 -3
- package/src/components/screens/businesses/business.tsx +21 -9
- package/src/components/screens/charges/charge.tsx +22 -9
- package/src/components/transactions-table/cells/counterparty.tsx +9 -2
- package/src/components/transactions-table/cells-legacy/counterparty.tsx +9 -2
- package/src/gql/graphql.ts +1554 -4842
- package/src/index.tsx +4 -22
- package/src/providers/auth-guard.tsx +14 -23
- package/src/providers/index.tsx +7 -2
- package/src/providers/urql-client.ts +86 -0
- package/src/providers/urql.tsx +7 -12
- package/src/providers/user-provider.tsx +3 -2
- package/src/router/config.tsx +534 -0
- package/src/router/layouts/dashboard-layout.tsx +20 -0
- package/src/router/layouts/root-layout.tsx +69 -0
- package/src/router/loaders/auth-loader.ts +32 -0
- package/src/router/loaders/business-loader.ts +25 -0
- package/src/router/loaders/charge-loader.ts +25 -0
- package/src/router/loaders/index.ts +17 -0
- package/src/router/routes.ts +88 -0
- package/src/router/types.ts +68 -0
- package/dist/assets/index-B2UYAO1O.css +0 -1
- package/dist/assets/index-BexxGuN6.js +0 -1224
- package/src/components/common/buttons/button-with-label.tsx +0 -41
- package/src/components/common/buttons/button.tsx +0 -44
package/src/index.tsx
CHANGED
|
@@ -1,32 +1,14 @@
|
|
|
1
1
|
import { StrictMode } from 'react';
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
createRoutesFromElements,
|
|
6
|
-
Route,
|
|
7
|
-
RouterProvider,
|
|
8
|
-
} from 'react-router-dom';
|
|
9
|
-
import { App } from './app.js';
|
|
10
|
-
import { Providers } from './providers/index.js';
|
|
3
|
+
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
|
|
4
|
+
import { routes } from './router/config.js';
|
|
11
5
|
import './index.css';
|
|
12
6
|
|
|
13
7
|
const rootElement = document.getElementById('root');
|
|
14
|
-
|
|
15
8
|
const root = createRoot(rootElement!);
|
|
16
9
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<Route
|
|
20
|
-
path="*"
|
|
21
|
-
element={
|
|
22
|
-
<Providers>
|
|
23
|
-
<App />
|
|
24
|
-
</Providers>
|
|
25
|
-
}
|
|
26
|
-
errorElement={<p>error</p>} // TODO: implement
|
|
27
|
-
/>,
|
|
28
|
-
),
|
|
29
|
-
);
|
|
10
|
+
// Create router with object-based configuration
|
|
11
|
+
const router = createBrowserRouter(routes);
|
|
30
12
|
|
|
31
13
|
root.render(
|
|
32
14
|
<StrictMode>
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import { createContext,
|
|
2
|
-
import { Route, Routes, useNavigate } from 'react-router-dom';
|
|
3
|
-
import { NetworkError } from '@/components/screens/network-error.js';
|
|
4
|
-
import { LoginPage } from '../components/login-page.js';
|
|
1
|
+
import { createContext, useMemo, useState, type ReactNode } from 'react';
|
|
5
2
|
import { UserService } from '../services/user-service.js';
|
|
6
3
|
|
|
7
4
|
type ContextType = {
|
|
@@ -14,25 +11,19 @@ export const AuthContext = createContext<ContextType>({
|
|
|
14
11
|
setAuthService: () => void 0,
|
|
15
12
|
});
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
/**
|
|
15
|
+
* AuthProvider - provides authentication context
|
|
16
|
+
* Auth routing logic is now handled by route loaders
|
|
17
|
+
*/
|
|
18
|
+
export const AuthProvider = ({ children }: { children?: ReactNode }): ReactNode => {
|
|
19
|
+
// Use lazy initialization to prevent creating new UserService on every render
|
|
20
|
+
const [authService, setAuthService] = useState<UserService>(() => new UserService());
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
// Memoize the context value to prevent unnecessary re-renders
|
|
23
|
+
const contextValue = useMemo(() => ({ authService, setAuthService }), [authService]);
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
if (!loggedIn) {
|
|
25
|
-
navigate('/login');
|
|
26
|
-
}
|
|
27
|
-
}, [loggedIn, navigate]);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<AuthContext.Provider value={{ authService, setAuthService }}>
|
|
31
|
-
<Routes>
|
|
32
|
-
<Route path="/login" element={<LoginPage />} />
|
|
33
|
-
<Route path="/network-error" element={<NetworkError />} />
|
|
34
|
-
<Route path="*" element={children} />
|
|
35
|
-
</Routes>
|
|
36
|
-
</AuthContext.Provider>
|
|
37
|
-
);
|
|
25
|
+
return <AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>;
|
|
38
26
|
};
|
|
27
|
+
|
|
28
|
+
// Keep AuthGuard as alias for backwards compatibility
|
|
29
|
+
export const AuthGuard = AuthProvider;
|
package/src/providers/index.tsx
CHANGED
|
@@ -5,9 +5,14 @@ import { red } from '@mui/material/colors';
|
|
|
5
5
|
import { createTheme } from '@mui/material/styles';
|
|
6
6
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
7
7
|
import { Toaster } from '../components/ui/sonner.js';
|
|
8
|
-
import { AuthGuard } from './auth-guard.js';
|
|
8
|
+
import { AuthContext, AuthGuard, AuthProvider } from './auth-guard.js';
|
|
9
9
|
import { UrqlProvider } from './urql.js';
|
|
10
|
-
import { UserProvider } from './user-provider.js';
|
|
10
|
+
import { UserContext, UserProvider, type UserInfo } from './user-provider.js';
|
|
11
|
+
|
|
12
|
+
export { AuthGuard, AuthProvider, AuthContext };
|
|
13
|
+
export { FiltersContext } from './filters-context.js';
|
|
14
|
+
export { UrqlProvider };
|
|
15
|
+
export { UserProvider, UserContext, type UserInfo };
|
|
11
16
|
|
|
12
17
|
const queryClient = new QueryClient();
|
|
13
18
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createClient,
|
|
3
|
+
fetchExchange,
|
|
4
|
+
mapExchange,
|
|
5
|
+
type AnyVariables,
|
|
6
|
+
type Client,
|
|
7
|
+
type Operation,
|
|
8
|
+
} from 'urql';
|
|
9
|
+
import { authExchange } from '@urql/exchange-auth';
|
|
10
|
+
import { UserService } from '../services/user-service.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Singleton URQL client for use in loaders and server-side operations
|
|
14
|
+
* This is separate from the Provider client to avoid React context dependencies
|
|
15
|
+
*/
|
|
16
|
+
let globalClient: Client | null = null;
|
|
17
|
+
|
|
18
|
+
export function getUrqlClient(): Client {
|
|
19
|
+
if (globalClient) {
|
|
20
|
+
return globalClient;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const authService = new UserService();
|
|
24
|
+
|
|
25
|
+
let url: string;
|
|
26
|
+
switch (import.meta.env.MODE) {
|
|
27
|
+
case 'production': {
|
|
28
|
+
url = 'https://accounter.onrender.com/graphql';
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case 'staging': {
|
|
32
|
+
url = 'https://accounter-staging.onrender.com/graphql';
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
default: {
|
|
36
|
+
url = 'http://localhost:4000/graphql';
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
globalClient = createClient({
|
|
42
|
+
url,
|
|
43
|
+
exchanges: [
|
|
44
|
+
mapExchange({
|
|
45
|
+
onResult(result) {
|
|
46
|
+
if (result.error?.networkError) {
|
|
47
|
+
console.error('Network Error:', result.error.networkError);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
}),
|
|
51
|
+
authExchange(async utils => {
|
|
52
|
+
return {
|
|
53
|
+
addAuthToOperation(operation): Operation<void, AnyVariables> {
|
|
54
|
+
const token = authService.authToken();
|
|
55
|
+
if (!token) {
|
|
56
|
+
return operation;
|
|
57
|
+
}
|
|
58
|
+
return utils.appendHeaders(operation, {
|
|
59
|
+
Authorization: token,
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
didAuthError(error, _operation): boolean {
|
|
63
|
+
return (
|
|
64
|
+
error?.response?.status === 401 ||
|
|
65
|
+
error?.graphQLErrors?.some(e => e.extensions?.code === 'FORBIDDEN')
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
async refreshAuth(): Promise<void> {
|
|
69
|
+
authService.logout();
|
|
70
|
+
// Redirect handled by route loader
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}),
|
|
74
|
+
fetchExchange,
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return globalClient;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Reset the global client (useful for tests or logout)
|
|
83
|
+
*/
|
|
84
|
+
export function resetUrqlClient(): void {
|
|
85
|
+
globalClient = null;
|
|
86
|
+
}
|
package/src/providers/urql.tsx
CHANGED
|
@@ -9,23 +9,23 @@ import {
|
|
|
9
9
|
type Operation,
|
|
10
10
|
} from 'urql';
|
|
11
11
|
import { authExchange } from '@urql/exchange-auth';
|
|
12
|
+
import { ROUTES } from '../router/routes.js';
|
|
12
13
|
import { AuthContext } from './auth-guard.js';
|
|
13
14
|
|
|
14
15
|
export function UrqlProvider({ children }: { children?: ReactNode }): ReactNode {
|
|
15
16
|
const { authService } = useContext(AuthContext);
|
|
16
17
|
const navigate = useNavigate();
|
|
18
|
+
|
|
19
|
+
// Track login state to trigger token updates
|
|
17
20
|
const loggedIn = authService.isLoggedIn();
|
|
18
21
|
|
|
19
22
|
const token = useMemo(() => {
|
|
20
23
|
const token = authService.authToken();
|
|
21
24
|
return token;
|
|
22
|
-
|
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- loggedIn is needed to trigger token refresh on login
|
|
26
|
+
}, [authService, loggedIn]);
|
|
23
27
|
|
|
24
28
|
const client = useMemo(() => {
|
|
25
|
-
if (!loggedIn) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
29
|
let url: string;
|
|
30
30
|
switch (import.meta.env.MODE) {
|
|
31
31
|
case 'production': {
|
|
@@ -47,16 +47,11 @@ export function UrqlProvider({ children }: { children?: ReactNode }): ReactNode
|
|
|
47
47
|
exchanges: [
|
|
48
48
|
mapExchange({
|
|
49
49
|
onResult(result) {
|
|
50
|
-
if (result.error?.networkError) {
|
|
51
|
-
console.error('Network Error:', result.error.networkError);
|
|
52
|
-
navigate('/network-error');
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
50
|
const isAuthError =
|
|
56
51
|
result?.error?.graphQLErrors.some(e => e.extensions?.code === 'FORBIDDEN') ||
|
|
57
52
|
result?.error?.response?.status === 401;
|
|
58
53
|
if (isAuthError) {
|
|
59
|
-
navigate(
|
|
54
|
+
navigate(ROUTES.LOGIN, {
|
|
60
55
|
state: { message: 'You are not authorized to access this page' },
|
|
61
56
|
});
|
|
62
57
|
}
|
|
@@ -86,7 +81,7 @@ export function UrqlProvider({ children }: { children?: ReactNode }): ReactNode
|
|
|
86
81
|
fetchExchange,
|
|
87
82
|
],
|
|
88
83
|
});
|
|
89
|
-
}, [
|
|
84
|
+
}, [navigate, token, authService]);
|
|
90
85
|
|
|
91
86
|
useEffect(() => {
|
|
92
87
|
if (!client) {
|
|
@@ -54,13 +54,14 @@ export function UserProvider({ children }: { children?: ReactNode }): ReactNode
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
// update active user
|
|
57
|
-
const currentUser = authService.currentUser();
|
|
58
57
|
useEffect(() => {
|
|
58
|
+
const currentUser = authService.currentUser();
|
|
59
59
|
if (!equal(currentUser, user)) {
|
|
60
60
|
setUser(currentUser);
|
|
61
61
|
fetchUserContext();
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- authService and fetchUserContext are stable
|
|
64
|
+
}, [user]);
|
|
64
65
|
|
|
65
66
|
// on user defaults fetched, update user defaults
|
|
66
67
|
useEffect(() => {
|