Skip to content

Commit

Permalink
fix admin dashboard (#328)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gentille-dev authored and Virgile1k committed Oct 23, 2023
1 parent 5fcdb3e commit 9ac9a66
Show file tree
Hide file tree
Showing 11 changed files with 585 additions and 14,820 deletions.
1 change: 1 addition & 0 deletions atlp-pulse-fn
Submodule atlp-pulse-fn added at db0c6f
15,033 changes: 247 additions & 14,786 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"homepage": "https://github.com/atlp-rwanda/atlp-pulse-fn#readme",
"dependencies": {
"@apollo/client": "^3.7.17",
"@apollo/client": "^3.8.5",
"@babel/preset-react": "^7.22.5",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
Expand Down Expand Up @@ -72,7 +72,7 @@
"file-saver": "^2.0.5",
"flowbite-react": "^0.5.0",
"framer-motion": "^6.5.1",
"graphql": "^16.7.1",
"graphql-tag": "^2.12.6",
"i18next": "^21.10.0",
"i18next-browser-languagedetector": "^7.1.0",
"i18next-xhr-backend": "^3.2.2",
Expand All @@ -91,6 +91,7 @@
"react-hook-form": "^7.45.2",
"react-i18next": "^11.18.6",
"react-icons": "^4.10.1",
"react-otp-input": "^3.1.0",
"react-pdf": "^7.3.3",
"react-pdf-js": "^5.1.0",
"react-router": "^6.14.1",
Expand Down Expand Up @@ -146,7 +147,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"faker": "5.5.3",
"file-loader": "^6.2.0",
"graphql": "^16.7.1",
"graphql": "^16.8.1",
"html-webpack-plugin": "^5.5.0",
"husky": "^8.0.1",
"install": "^0.13.0",
Expand Down
21 changes: 21 additions & 0 deletions src/Mutations/Twofactor2fa.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable */
// mutations.ts
import gql from 'graphql-tag';

export const ENABLE_TWO_FACTOR_AUTH = gql`
mutation EnableTwoFactorAuth($email: String!) {
enableTwoFactorAuth(email: $email)
}
`;

export const DISABLE_TWO_FACTOR_AUTH = gql`
mutation DisableTwoFactorAuth($email: String!) {
disableTwoFactorAuth(email: $email)
}
`;

export const VERIFY_ONE_TIME_CODE = gql`
mutation VerifyOneTimeCode($email: String!, $code: String!) {
verifyOneTimeCode(email: $email, code: $code)
}
`;
68 changes: 68 additions & 0 deletions src/components/twofactor/ Enable2fa.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-disable */
import React, { useState } from 'react';
import { useMutation, useQuery } from '@apollo/client';
import { ENABLE_TWO_FACTOR_AUTH } from '../../Mutations/Twofactor2fa';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import VerifyOneTimeCodeComponent from "../../components/twofactor/Verify2fa";
import { GET_PROFILE } from '../../Mutations/User'; // Import your GET_PROFILE query
import Loader1 from '../../components/loaders/loader2/index'; // Import your loader component

const EnableTwoFactorAuthComponent: React.FC = () => {
const [isTwoFactorEnabled, setIsTwoFactorEnabled] = useState(false);
const [isLoading, setIsLoading] = useState(false);

// Fetch user's profile to get the email
const { loading, error, data } = useQuery(GET_PROFILE);

const [enableTwoFactorAuth] = useMutation(ENABLE_TWO_FACTOR_AUTH);

const handleEnableTwoFactorAuth = async () => {
try {
setIsLoading(true);

// Check if the GET_PROFILE query has loaded
if (loading) {
toast.error('Profile data is loading. Please wait.');
setIsLoading(false);
return;
}
if (error) {
toast.error('Error fetching profile data. Please try again.');
setIsLoading(false);
return;
}

// Extract the email from the profile data
const userProfile = data.getProfile;
const userProfileEmail = userProfile.user.email;

// Send the OTP to the user's email
const response = await enableTwoFactorAuth({
variables: { email: userProfileEmail },
});

console.log(response.data.enableTwoFactorAuth);
toast.success('OTP check email sent! Check your inbox.');
setIsTwoFactorEnabled(true);
} catch (error) {
console.error(error);
toast.error('Error sending OTP check email. Please try again.');
} finally {
setIsLoading(false);
}
};

return (
<div className='border-b border-gray-400 pt-2 pb-1'>
<button onClick={handleEnableTwoFactorAuth} disabled={isLoading}>
{isLoading ? <Loader1 /> : 'Enable 2FA'}
</button>

{isTwoFactorEnabled && <VerifyOneTimeCodeComponent />}
</div>
);
};

export default EnableTwoFactorAuthComponent;

63 changes: 63 additions & 0 deletions src/components/twofactor/Disable2fa.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* eslint-disable */
import React, { useState } from 'react';
import { useMutation, useQuery } from '@apollo/client';
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { DISABLE_TWO_FACTOR_AUTH } from '../../Mutations/Twofactor2fa';
import Loader1 from '../../components/loaders/loader2/index'; // Import your loader component
import { GET_PROFILE } from '../../Mutations/User'; // Import your GET_PROFILE query

const DisableTwoFactorAuthComponent: React.FC = () => {
const [isTwoFactorDisabled, setIsTwoFactorDisabled] = useState(false);
const [loading, setLoading] = useState(false); // State to manage loading state

// Fetch user's profile to get the email
const { error, data } = useQuery(GET_PROFILE);

const [disableTwoFactorAuth] = useMutation(DISABLE_TWO_FACTOR_AUTH);

const handleDisableTwoFactorAuth = async () => {
try {
// Check if the GET_PROFILE query has loaded
if (loading) {
toast.error('Profile data is loading. Please wait.');
return;
}
if (error) {
toast.error('Error fetching profile data. Please try again.');
return;
}

setLoading(true); // Set loading state to true

// Extract the email from the profile data
const userProfile = data.getProfile;
const userProfileEmail = userProfile.user.email;

// Disable two-factor authentication using the user's email
const response = await disableTwoFactorAuth({
variables: { email: userProfileEmail },
});

console.log(response.data.disableTwoFactorAuth);
toast.success('2FA Disabled'); // Display success toast
setIsTwoFactorDisabled(true);
} catch (error) {
console.error(error);
toast.error('Error disabling 2FA'); // Display error toast
} finally {
setLoading(false); // Set loading state back to false when done
}
};

return (
<div className='border-b border-gray-400 pt-2 pb-1 text-black-400'>
<button onClick={handleDisableTwoFactorAuth} disabled={loading}>
{loading ? <Loader1 /> : 'Disable 2FA'}
</button>
<ToastContainer />
</div>
);
};

export default DisableTwoFactorAuthComponent;
103 changes: 103 additions & 0 deletions src/components/twofactor/Verify2fa.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* eslint-disable */
import React, { useState, useEffect } from 'react';
import { useMutation, useQuery } from '@apollo/client';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import Loader1 from '../../components/loaders/loader2/index';
import { VERIFY_ONE_TIME_CODE } from '../../Mutations/Twofactor2fa';
import { GET_PROFILE } from '../../Mutations/User';

const VerifyOneTimeCodeComponent: React.FC = () => {
const [code, setCode] = useState('');
const [isCodeVerified, setIsCodeVerified] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(true);
const [isVerifying, setIsVerifying] = useState(false);

// Fetch user's profile to get the email
const { loading, error, data } = useQuery(GET_PROFILE);

const [verifyOneTimeCode] = useMutation(VERIFY_ONE_TIME_CODE);

const closeModal = () => {
setIsModalOpen(false);
};

useEffect(() => {
if (isModalOpen) {
// The modal is open, you can place any code to run when it opens here.
}
}, [isModalOpen]);

const handleVerifyOneTimeCode = async () => {
try {
setIsVerifying(true);

if (loading) {
toast.error('Profile data is loading. Please wait.');
return;
}
if (error) {
toast.error('Error fetching profile data. Please try again.');
return;
}

const userProfile = data.getProfile;
const userProfileEmail = userProfile.user.email;

const response = await verifyOneTimeCode({
variables: { email: userProfileEmail, code },
});

console.log(response.data.verifyOneTimeCode);

if (response.data.verifyOneTimeCode) {
toast.success('OTP verified successfully');
setIsCodeVerified(true);
closeModal();
}
} catch (error) {
console.error(error);
toast.error('Error verifying OTP');
} finally {
setIsVerifying(false);
}
};

return (
<div>
{isModalOpen && (
<div className="fixed inset-0 flex items-center justify-center z-50">
<div className="absolute inset-0 bg-gray-900 opacity-75"></div>
<div className="bg-white p-4 rounded-lg shadow-md z-10">
<button onClick={closeModal} className="absolute top-2 right-2 text-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
</button>
<input
type="text"
value={code}
onChange={(e) => setCode(e.target.value)}
placeholder="Enter one-time code"
className="border border-gray-300 p-2 w-full rounded text-black"
/>
<button
onClick={handleVerifyOneTimeCode}
className="bg-blue-500 text-white p-2 rounded mt-4"
disabled={isVerifying} // Disable the button while verifying
>
{isVerifying ? (
<Loader1 /> // Show the loader inside the button
) : (
'Verify Code'
)}
</button>
{isCodeVerified && <div className="mt-4">OTP Verified Successfully!</div>}
</div>
</div>
)}
</div>
);
};

export default VerifyOneTimeCodeComponent;
8 changes: 8 additions & 0 deletions src/containers/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import Error from './../pages/Error';
import Skeleton from '../components/Skeleton';
import UserRegister from '../pages/Organization/UserRegister';
import Message from '../pages/Organization/Message';
// import VerifyOneTimeCodeComponent from '../components/twofactor/Verify2fa';

/* istanbul ignore next */
const OrgRegister = React.lazy(() => import('../pages/OrgRegister'));
/* istanbul ignore next */
Expand Down Expand Up @@ -92,6 +94,12 @@ function MainRoutes() {
<Route path="/docs/org-signup" element={<SignupOrgDocs />} />
<Route path="/docs/org-signin" element={<SigninOrgDocs />} />
<Route path="/noredirect" element={<Noredirect />} />

{/* <Route
path="/verify-otp"
element={<VerifyOneTimeCodeComponent />}
/> */}

<Route path="/pricing-form" element={<Pay />} />
</Route>
<Route path="*" element={<Error />} />
Expand Down
7 changes: 4 additions & 3 deletions src/pages/AdminDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function SupAdDashboard() {
const inviteModel = () => {
const newState = !inviteTraineeModel;
setInviteTraineeModel(newState);
// this is true
};

const [inviteUser] = useMutation(INVITE_USER_MUTATION, {
Expand Down Expand Up @@ -137,7 +138,7 @@ function SupAdDashboard() {
<div>
{/* <div className="bg-light-bg dark:bg-dark-frame-bg ">
<div className="flex items-left px-10 lg:px-60 pt-24 pb-8"> */}
<div className="flex gap-2 pt-5">
{/* <div className="flex gap-2 pt-5">
{user?.role === 'coordinator' || undefined ? (
''
) : (
Expand All @@ -151,7 +152,7 @@ function SupAdDashboard() {
{t('Invite an organization')}
</Button>
)}
</div>
</div> */}
</div>

{/* </div>
Expand All @@ -165,4 +166,4 @@ function SupAdDashboard() {
);
}

export default SupAdDashboard;
export default SupAdDashboard;
Loading

0 comments on commit 9ac9a66

Please sign in to comment.