Skip to content

Commit 335aed2

Browse files
committed
two-factor authentication with reactjs
0 parents  commit 335aed2

30 files changed

Lines changed: 2597 additions & 0 deletions

.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + React + TS</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>

package.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "2fa_reactjs",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite --host localhost --port 3000",
8+
"build": "tsc && vite build",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
"@hookform/resolvers": "^2.9.8",
13+
"axios": "^0.27.2",
14+
"qrcode": "^1.5.1",
15+
"react": "^18.2.0",
16+
"react-dom": "^18.2.0",
17+
"react-hook-form": "^7.36.1",
18+
"react-router-dom": "^6.4.1",
19+
"react-toastify": "^9.0.8",
20+
"tailwind-merge": "^1.6.0",
21+
"zod": "^3.19.1",
22+
"zustand": "^4.1.1"
23+
},
24+
"devDependencies": {
25+
"@types/qrcode": "^1.5.0",
26+
"@types/react": "^18.0.17",
27+
"@types/react-dom": "^18.0.6",
28+
"@vitejs/plugin-react": "^2.1.0",
29+
"autoprefixer": "^10.4.12",
30+
"postcss": "^8.4.16",
31+
"tailwindcss": "^3.1.8",
32+
"typescript": "^4.6.4",
33+
"vite": "^3.1.0"
34+
}
35+
}

postcss.config.cjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
}

public/vite.svg

Lines changed: 1 addition & 0 deletions
Loading

src/App.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { useRoutes } from "react-router-dom";
2+
import routes from "./router";
3+
4+
function App() {
5+
const content = useRoutes(routes);
6+
return content;
7+
}
8+
9+
export default App;

src/api/authApi.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import axios from "axios";
2+
3+
const BASE_URL = "http://localhost:8000/api/";
4+
5+
export const authApi = axios.create({
6+
baseURL: BASE_URL,
7+
withCredentials: true,
8+
});
9+
10+
authApi.defaults.headers.common["Content-Type"] = "application/json";

src/api/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export interface IUser {
2+
id: string;
3+
name: string;
4+
email: string;
5+
otp_enabled: string;
6+
}
7+
8+
export interface GenericResponse {
9+
status: string;
10+
message: string;
11+
}
12+
13+
export interface ILoginResponse {
14+
status: string;
15+
user: IUser;
16+
}

src/assets/react.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/FormInput.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import { useFormContext } from 'react-hook-form';
3+
4+
type FormInputProps = {
5+
label: string;
6+
name: string;
7+
type?: string;
8+
};
9+
10+
const FormInput: React.FC<FormInputProps> = ({
11+
label,
12+
name,
13+
type = 'text',
14+
}) => {
15+
const {
16+
register,
17+
formState: { errors },
18+
} = useFormContext();
19+
return (
20+
<div className=''>
21+
<label htmlFor={name} className='block text-ct-blue-600 mb-3'>
22+
{label}
23+
</label>
24+
<input
25+
type={type}
26+
placeholder=' '
27+
className='block w-full rounded-2xl appearance-none focus:outline-none py-2 px-4'
28+
{...register(name)}
29+
/>
30+
{errors[name] && (
31+
<span className='text-red-500 text-xs pt-1 block'>
32+
{errors[name]?.message as string}
33+
</span>
34+
)}
35+
</div>
36+
);
37+
};
38+
39+
export default FormInput;

0 commit comments

Comments
 (0)