Skip to content

Commit

Permalink
✨ Implement activate user
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinbreiz committed Sep 18, 2023
1 parent 6b8a4c3 commit a59a7f2
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { AuthProvider } from '@providers/AuthProvider';
import './i18n/i18n';
import InvitationSignup from '@pages/Invitation';

function App() {
const PrivateRoute = ({ component: Component, ...rest }) => {
Expand Down Expand Up @@ -58,6 +59,7 @@ function App() {
<PrivateRoute path="/" exact component={HomePage} />
<PrivateRoute path="/profile" component={ProfilePage} />
<PrivateRoute path="/honeypot" component={HoneyPotPage} />
<Route path="/activate/:activationToken" component={InvitationSignup} />
</Switch>
</div>
</ThemeProvider>
Expand Down
4 changes: 4 additions & 0 deletions src/contexts/AuthContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ interface AuthContextProps {
isLoggedIn: boolean;
token: string | null;
login: (email: string, password: string) => void;
loginWithToken: (token: string) => void;
logout: () => void;
}

Expand All @@ -13,6 +14,9 @@ const defaultAuth: AuthContextProps = {
login: function (email: string, password: string): void {
throw new Error('Function not implemented.');
},
loginWithToken: function (ematokenil: string): void {
throw new Error('Function not implemented.');
},
logout: function (): void {
throw new Error('Function not implemented.');
}
Expand Down
23 changes: 23 additions & 0 deletions src/hooks/backend/userService/useActivateUserRPC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import { transport } from "../../../environment";
import { UserClient } from '@protos/user.client';
import { ActivateUserRequest } from '@protos/user';

const useActivateUserRPC = () => {
const client = React.useMemo(() => new UserClient(transport), []);

const activateUser = React.useCallback( async (token: string, password: string) => {
const request: ActivateUserRequest = ActivateUserRequest.create();
request.token = token;
request.password = password;
const response = await client.activateUser(request, {}).response;
return response.token;
}, []);

return {
activateUser,
};

};

export default useActivateUserRPC;
62 changes: 62 additions & 0 deletions src/pages/Invitation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
import { Box, Paper, Typography, TextField, Button } from '@mui/material';
import useActivateUserRPC from '@hooks/backend/userService/useActivateUserRPC';
import AuthContext from '@contexts/AuthContext';
import { toast } from 'react-toastify';
import { useTranslation } from 'react-i18next';

const InvitationSignup: React.FC = () => {
const [password, setPassword] = useState<string>('');
const [submitted, setSubmitted] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);

const { loginWithToken } = React.useContext(AuthContext);
const { activateUser } = useActivateUserRPC();
const { activationToken } = useParams<{ activationToken: string }>();

const { t } = useTranslation();

const signIn = async () => {
try {
setError(null); // Clear any previous errors before attempting the operation again
const loginToken = await activateUser(activationToken, password);
loginWithToken(loginToken);
toast.success(t("loginPage.loginSuccess"));
setSubmitted(true);
} catch (err) {
setError("Invitation déjà utilisée!"); // Set the error state
}
};

return (
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: 'calc(100vh - 110px)' }}>
<Paper sx={{ p: 2, width: '25em' }}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<Typography variant="h6">Choisissez votre nouveau mot de passe</Typography>
{submitted && (<Typography>Votre compte a été correctement créé</Typography>)}
{!submitted && (
<>
<TextField
type="password"
name='password'
label="Mot de passe"
value={password}
required
onChange={(e) => setPassword(e.target.value)}
/>
{error && (
<Typography color="error" variant="body2">{error}</Typography> // Display error inline
)}
<Button type="submit" variant="contained" color="primary" onClick={signIn} >
Créer un compte
</Button>
</>
)}
</Box>
</Paper>
</Box>
);
}

export default InvitationSignup;
14 changes: 13 additions & 1 deletion src/providers/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ export const AuthProvider = ({ children }) => {
throw error;
}
}, []);

const loginWithToken = React.useCallback(async (token: string) => {
try {
localStorage.setItem('token', token);
console.log(token);
setToken(token);
setIsLoggedIn(true);
history.push('/');
} catch (error) {
throw error;
}
}, []);

const logout = React.useCallback(async () => {
try {
Expand All @@ -53,7 +65,7 @@ export const AuthProvider = ({ children }) => {
}, []);

return (
<AuthContext.Provider value={{ isLoggedIn, token, login, logout }}>
<AuthContext.Provider value={{ isLoggedIn, token, login, loginWithToken, logout }}>
{children}
</AuthContext.Provider>
);
Expand Down

0 comments on commit a59a7f2

Please sign in to comment.