Fix mock mode transition to regular mode on login (#361)
This commit is contained in:
28
front/src/AppWrapper.tsx
Normal file
28
front/src/AppWrapper.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { StrictMode } from 'react';
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import { ApolloProvider } from '@apollo/client';
|
||||||
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
import { isMockModeState } from '@/auth/states/isMockModeState';
|
||||||
|
|
||||||
|
import { AppThemeProvider } from './providers/AppThemeProvider';
|
||||||
|
import { AuthProvider } from './providers/AuthProvider';
|
||||||
|
import { apiClient, mockClient } from './apollo';
|
||||||
|
import { App } from './App';
|
||||||
|
|
||||||
|
export function AppWrapper() {
|
||||||
|
const [isMockMode] = useRecoilState(isMockModeState);
|
||||||
|
return (
|
||||||
|
<ApolloProvider client={isMockMode ? mockClient : apiClient}>
|
||||||
|
<BrowserRouter>
|
||||||
|
<AuthProvider>
|
||||||
|
<AppThemeProvider>
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>
|
||||||
|
</AppThemeProvider>
|
||||||
|
</AuthProvider>
|
||||||
|
</BrowserRouter>
|
||||||
|
</ApolloProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
ApolloClient,
|
ApolloClient,
|
||||||
|
ApolloLink,
|
||||||
createHttpLink,
|
createHttpLink,
|
||||||
from,
|
from,
|
||||||
InMemoryCache,
|
InMemoryCache,
|
||||||
@ -11,6 +12,8 @@ import { RestLink } from 'apollo-link-rest';
|
|||||||
|
|
||||||
import { CommentThreadTarget } from './generated/graphql';
|
import { CommentThreadTarget } from './generated/graphql';
|
||||||
import { getTokensFromRefreshToken } from './modules/auth/services/AuthService';
|
import { getTokensFromRefreshToken } from './modules/auth/services/AuthService';
|
||||||
|
import { mockedCompaniesData } from './testing/mock-data/companies';
|
||||||
|
import { mockedUsersData } from './testing/mock-data/users';
|
||||||
|
|
||||||
const apiLink = createHttpLink({
|
const apiLink = createHttpLink({
|
||||||
uri: `${process.env.REACT_APP_API_URL}`,
|
uri: `${process.env.REACT_APP_API_URL}`,
|
||||||
@ -98,3 +101,25 @@ export const authClient = new ApolloClient({
|
|||||||
link: authLink,
|
link: authLink,
|
||||||
cache: new InMemoryCache(),
|
cache: new InMemoryCache(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mockLink = new ApolloLink((operation, forward) => {
|
||||||
|
return forward(operation).map((response) => {
|
||||||
|
if (operation.operationName === 'GetCompanies') {
|
||||||
|
return { data: { companies: mockedCompaniesData } };
|
||||||
|
}
|
||||||
|
if (operation.operationName === 'GetCurrentUser') {
|
||||||
|
return { data: { users: [mockedUsersData[0]] } };
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export const mockClient = new ApolloClient({
|
||||||
|
link: from([mockLink, apiLink]),
|
||||||
|
cache: new InMemoryCache(),
|
||||||
|
defaultOptions: {
|
||||||
|
query: {
|
||||||
|
fetchPolicy: 'cache-first',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@ -1,35 +1,21 @@
|
|||||||
import React, { StrictMode } from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
|
||||||
import { ApolloProvider } from '@apollo/client';
|
|
||||||
import { RecoilRoot } from 'recoil';
|
import { RecoilRoot } from 'recoil';
|
||||||
|
|
||||||
import '@emotion/react';
|
import '@emotion/react';
|
||||||
|
|
||||||
import { ThemeType } from './modules/ui/layout/styles/themes';
|
import { ThemeType } from './modules/ui/layout/styles/themes';
|
||||||
import { AppThemeProvider } from './providers/AppThemeProvider';
|
import { AppWrapper } from './AppWrapper';
|
||||||
import { AuthProvider } from './providers/AuthProvider';
|
|
||||||
import { apiClient } from './apollo';
|
|
||||||
import { App } from './App';
|
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement,
|
document.getElementById('root') as HTMLElement,
|
||||||
);
|
);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<RecoilRoot>
|
<RecoilRoot>
|
||||||
<ApolloProvider client={apiClient}>
|
<AppWrapper />
|
||||||
<BrowserRouter>
|
|
||||||
<AuthProvider>
|
|
||||||
<AppThemeProvider>
|
|
||||||
<StrictMode>
|
|
||||||
<App />
|
|
||||||
</StrictMode>
|
|
||||||
</AppThemeProvider>
|
|
||||||
</AuthProvider>
|
|
||||||
</BrowserRouter>
|
|
||||||
</ApolloProvider>
|
|
||||||
</RecoilRoot>,
|
</RecoilRoot>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
import { graphql, setupWorker } from 'msw';
|
|
||||||
|
|
||||||
import { mockedCompaniesData } from '~/testing/mock-data/companies';
|
|
||||||
import { mockedUsersData } from '~/testing/mock-data/users';
|
|
||||||
|
|
||||||
export function useMockData() {
|
|
||||||
const worker = setupWorker(...graphqlMocks);
|
|
||||||
worker.start({ quiet: true, onUnhandledRequest: 'bypass' });
|
|
||||||
}
|
|
||||||
|
|
||||||
const graphqlMocks = [
|
|
||||||
graphql.query('GetCompanies', (req, res, ctx) => {
|
|
||||||
return res(
|
|
||||||
ctx.data({
|
|
||||||
companies: mockedCompaniesData,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
|
|
||||||
graphql.query('GetCurrentUser', (req, res, ctx) => {
|
|
||||||
return res(
|
|
||||||
ctx.data({
|
|
||||||
users: [mockedUsersData[0]],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
6
front/src/modules/auth/states/isMockModeState.ts
Normal file
6
front/src/modules/auth/states/isMockModeState.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { atom } from 'recoil';
|
||||||
|
|
||||||
|
export const isMockModeState = atom({
|
||||||
|
key: 'isMockModeState',
|
||||||
|
default: false,
|
||||||
|
});
|
||||||
@ -10,9 +10,9 @@ import { HorizontalSeparator } from '@/auth/components/ui/HorizontalSeparator';
|
|||||||
import { Logo } from '@/auth/components/ui/Logo';
|
import { Logo } from '@/auth/components/ui/Logo';
|
||||||
import { Modal } from '@/auth/components/ui/Modal';
|
import { Modal } from '@/auth/components/ui/Modal';
|
||||||
import { Title } from '@/auth/components/ui/Title';
|
import { Title } from '@/auth/components/ui/Title';
|
||||||
import { useMockData } from '@/auth/hooks/useMockData';
|
|
||||||
import { hasAccessToken } from '@/auth/services/AuthService';
|
import { hasAccessToken } from '@/auth/services/AuthService';
|
||||||
import { authFlowUserEmailState } from '@/auth/states/authFlowUserEmailState';
|
import { authFlowUserEmailState } from '@/auth/states/authFlowUserEmailState';
|
||||||
|
import { isMockModeState } from '@/auth/states/isMockModeState';
|
||||||
import { PrimaryButton } from '@/ui/components/buttons/PrimaryButton';
|
import { PrimaryButton } from '@/ui/components/buttons/PrimaryButton';
|
||||||
import { SecondaryButton } from '@/ui/components/buttons/SecondaryButton';
|
import { SecondaryButton } from '@/ui/components/buttons/SecondaryButton';
|
||||||
import { TextInput } from '@/ui/components/inputs/TextInput';
|
import { TextInput } from '@/ui/components/inputs/TextInput';
|
||||||
@ -28,17 +28,19 @@ const StyledContentContainer = styled.div`
|
|||||||
export function Index() {
|
export function Index() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
useMockData();
|
const [, setMockMode] = useRecoilState(isMockModeState);
|
||||||
|
|
||||||
const [authFlowUserEmail, setAuthFlowUserEmail] = useRecoilState(
|
const [authFlowUserEmail, setAuthFlowUserEmail] = useRecoilState(
|
||||||
authFlowUserEmailState,
|
authFlowUserEmailState,
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setMockMode(true);
|
||||||
|
|
||||||
if (hasAccessToken()) {
|
if (hasAccessToken()) {
|
||||||
navigate('/');
|
navigate('/');
|
||||||
}
|
}
|
||||||
}, [navigate]);
|
}, [navigate, setMockMode]);
|
||||||
|
|
||||||
const onGoogleLoginClick = useCallback(() => {
|
const onGoogleLoginClick = useCallback(() => {
|
||||||
window.location.href = process.env.REACT_APP_AUTH_URL + '/google' || '';
|
window.location.href = process.env.REACT_APP_AUTH_URL + '/google' || '';
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { SubTitle } from '@/auth/components/ui/SubTitle';
|
|||||||
import { Title } from '@/auth/components/ui/Title';
|
import { Title } from '@/auth/components/ui/Title';
|
||||||
import { getTokensFromLoginToken } from '@/auth/services/AuthService';
|
import { getTokensFromLoginToken } from '@/auth/services/AuthService';
|
||||||
import { authFlowUserEmailState } from '@/auth/states/authFlowUserEmailState';
|
import { authFlowUserEmailState } from '@/auth/states/authFlowUserEmailState';
|
||||||
|
import { isMockModeState } from '@/auth/states/isMockModeState';
|
||||||
import { PrimaryButton } from '@/ui/components/buttons/PrimaryButton';
|
import { PrimaryButton } from '@/ui/components/buttons/PrimaryButton';
|
||||||
import { TextInput } from '@/ui/components/inputs/TextInput';
|
import { TextInput } from '@/ui/components/inputs/TextInput';
|
||||||
import { Companies } from '~/pages/companies/Companies';
|
import { Companies } from '~/pages/companies/Companies';
|
||||||
@ -35,6 +36,7 @@ const StyledErrorContainer = styled.div`
|
|||||||
|
|
||||||
export function PasswordLogin() {
|
export function PasswordLogin() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [, setMockMode] = useRecoilState(isMockModeState);
|
||||||
|
|
||||||
const prefillPassword =
|
const prefillPassword =
|
||||||
process.env.NODE_ENV === 'development' ? 'applecar2025' : '';
|
process.env.NODE_ENV === 'development' ? 'applecar2025' : '';
|
||||||
@ -60,19 +62,22 @@ export function PasswordLogin() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.ok) {
|
if (!response.ok) {
|
||||||
const { loginToken } = await response.json();
|
const errorData = await response.json();
|
||||||
if (!loginToken) {
|
setFormError(errorData.message);
|
||||||
// TODO Display error message
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await getTokensFromLoginToken(loginToken.token);
|
|
||||||
navigate('/');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const errorData = await response.json();
|
const { loginToken } = await response.json();
|
||||||
setFormError(errorData.message);
|
|
||||||
}, [authFlowUserEmail, internalPassword, navigate]);
|
if (!loginToken) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await getTokensFromLoginToken(loginToken.token);
|
||||||
|
setMockMode(false);
|
||||||
|
|
||||||
|
navigate('/');
|
||||||
|
}, [authFlowUserEmail, internalPassword, navigate, setMockMode]);
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'enter',
|
'enter',
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
"prisma:generate-nest-graphql": "npx prisma generate --generator nestgraphql && eslint \"src/core/@generated/**\" --fix",
|
"prisma:generate-nest-graphql": "npx prisma generate --generator nestgraphql && eslint \"src/core/@generated/**\" --fix",
|
||||||
"prisma:migrate": "npx prisma migrate deploy",
|
"prisma:migrate": "npx prisma migrate deploy",
|
||||||
"prisma:seed": "npx prisma db seed",
|
"prisma:seed": "npx prisma db seed",
|
||||||
"prisma:reset": "yarn prisma:generate-client && yarn prisma:generate-nest-graphql && npx prisma migrate reset"
|
"prisma:reset": "npx prisma migrate reset && eslint \"src/core/@generated/**\" --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/server": "^4.7.3",
|
"@apollo/server": "^4.7.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user