ariansyahdedy commited on
Commit
4fb0c68
·
0 Parent(s):

Initial commit with clean Git repository

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .eslintrc.cjs +21 -0
  2. .gitattributes +1 -0
  3. .gitignore +3 -0
  4. README.md +8 -0
  5. index.html +12 -0
  6. package-lock.json +0 -0
  7. package.json +38 -0
  8. postcss.config.js +6 -0
  9. public/HiDigi.jpg +3 -0
  10. public/HiDigiH.jpg +3 -0
  11. public/bot.png +0 -0
  12. public/vite.svg +1 -0
  13. public/you.png +0 -0
  14. src/App.jsx +42 -0
  15. src/assets/react.svg +1 -0
  16. src/chartSetup.js +25 -0
  17. src/components/ChatMessage.jsx +47 -0
  18. src/components/ConfigForm.jsx +131 -0
  19. src/components/ERPCredentials.jsx +112 -0
  20. src/components/ForgotPassword.jsx +48 -0
  21. src/components/HomeDashboard.jsx +16 -0
  22. src/components/InvoiceForm.jsx +132 -0
  23. src/components/Login.jsx +84 -0
  24. src/components/Logout.jsx +20 -0
  25. src/components/OCRDashboard.jsx +147 -0
  26. src/components/OCRHeader.jsx +20 -0
  27. src/components/OCRQuota.jsx +16 -0
  28. src/components/OCRSidebar.jsx +67 -0
  29. src/components/OCRTemplate.jsx +212 -0
  30. src/components/PrivacyPolicy.jsx +16 -0
  31. src/components/ProtectedRoute.jsx +39 -0
  32. src/components/Register.jsx +171 -0
  33. src/components/SideBarGPT.jsx +18 -0
  34. src/components/Terms.jsx +16 -0
  35. src/components/TextToSpeech.jsx +153 -0
  36. src/data/languageVoices.jsx +25 -0
  37. src/index.css +95 -0
  38. src/layouts/MainLayout.jsx +15 -0
  39. src/main.jsx +12 -0
  40. src/pages/AnalyticsPage.jsx +80 -0
  41. src/pages/ChatPage.jsx +66 -0
  42. src/pages/DocumentManagement.jsx +117 -0
  43. src/pages/ERPCredentialPage.jsx +7 -0
  44. src/pages/Home.jsx +7 -0
  45. src/pages/LoginPage.jsx +7 -0
  46. src/pages/OCRDashboardPage.jsx +12 -0
  47. src/pages/OCRTemplatePage.jsx +7 -0
  48. src/pages/TextToSpeechPage.jsx +7 -0
  49. src/services/api.js +185 -0
  50. src/services/axiosInstance.js +44 -0
.eslintrc.cjs ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ root: true,
3
+ env: { browser: true, es2020: true },
4
+ extends: [
5
+ 'eslint:recommended',
6
+ 'plugin:react/recommended',
7
+ 'plugin:react/jsx-runtime',
8
+ 'plugin:react-hooks/recommended',
9
+ ],
10
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
11
+ parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
12
+ settings: { react: { version: '18.2' } },
13
+ plugins: ['react-refresh'],
14
+ rules: {
15
+ 'react/jsx-no-target-blank': 'off',
16
+ 'react-refresh/only-export-components': [
17
+ 'warn',
18
+ { allowConstantExport: true },
19
+ ],
20
+ },
21
+ }
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.jpg filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ node_modules/
2
+ dist/
3
+ .env
README.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # React + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
index.html ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
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</title>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.jsx"></script>
11
+ </body>
12
+ </html>
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "frontendspeech",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "@fortawesome/fontawesome-svg-core": "^6.5.2",
14
+ "@fortawesome/free-solid-svg-icons": "^6.5.2",
15
+ "@fortawesome/react-fontawesome": "^0.2.2",
16
+ "@heroicons/react": "^1.0.6",
17
+ "axios": "^1.7.2",
18
+ "chart.js": "^4.4.3",
19
+ "jwt-decode": "^4.0.0",
20
+ "react": "^18.3.1",
21
+ "react-chartjs-2": "^5.2.0",
22
+ "react-dom": "^18.3.1",
23
+ "react-router-dom": "^6.24.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/react": "^18.3.3",
27
+ "@types/react-dom": "^18.3.0",
28
+ "@vitejs/plugin-react": "^4.3.1",
29
+ "autoprefixer": "^10.4.19",
30
+ "eslint": "^8.57.0",
31
+ "eslint-plugin-react": "^7.34.2",
32
+ "eslint-plugin-react-hooks": "^4.6.2",
33
+ "eslint-plugin-react-refresh": "^0.4.7",
34
+ "postcss": "^8.4.39",
35
+ "tailwindcss": "^3.4.4",
36
+ "vite": "^5.3.1"
37
+ }
38
+ }
postcss.config.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
public/HiDigi.jpg ADDED

Git LFS Details

  • SHA256: ec099dd09538686df9a056b317d4b6b449d34676a053e28027b830440213b93a
  • Pointer size: 132 Bytes
  • Size of remote file: 2.55 MB
public/HiDigiH.jpg ADDED

Git LFS Details

  • SHA256: 983e4ab5e974c23f36665240a369556281c2b00f6f216bcd8d5e60888bc6df16
  • Pointer size: 132 Bytes
  • Size of remote file: 3.48 MB
public/bot.png ADDED
public/vite.svg ADDED
public/you.png ADDED
src/App.jsx ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
2
+ import { useState } from 'react';
3
+ import Register from './components/Register';
4
+ import ConfigForm from './components/ConfigForm';
5
+ import Home from './pages/Home';
6
+ import TextToSpeechPage from './pages/TextToSpeechPage';
7
+ import LoginPage from './pages/LoginPage';
8
+ import ProtectedRoute from './components/ProtectedRoute';
9
+ import OCRDashboard from './pages/OCRDashboardPage';
10
+ import ERPCredential from './pages/ERPCredentialPage';
11
+ import OCRTemplate from './pages/OCRTemplatePage';
12
+ import Logout from './components/Logout';
13
+ import Chat from './pages/ChatPage';
14
+ import Analytics from './pages/AnalyticsPage';
15
+ import DocumentManagement from './pages/DocumentManagement';
16
+
17
+ function App() {
18
+ const [token, setToken] = useState(localStorage.getItem('token'));
19
+
20
+ return (
21
+ <Router>
22
+ <div className="min-h-screen flex flex-col">
23
+ <Routes>
24
+ <Route path="/" element={<Navigate to="/ocrdashboard" replace />} />
25
+ <Route path="/text-to-speech" element={<ProtectedRoute token={token}><TextToSpeechPage /></ProtectedRoute>} />
26
+ <Route path="/login" element={<LoginPage setToken={setToken} />} />
27
+ <Route path="/logout" element={<ProtectedRoute token={token}><Logout setToken={setToken} /></ProtectedRoute>} />
28
+ <Route path="/register" element={<Register />} />
29
+ <Route path="/ocrdashboard" element={<ProtectedRoute token={token}><OCRDashboard /></ProtectedRoute>} />
30
+ <Route path="/ocrtemplate" element={<ProtectedRoute token={token}><OCRTemplate /></ProtectedRoute>} />
31
+ <Route path="/erpcredential" element={<ProtectedRoute token={token}><ERPCredential /></ProtectedRoute>} />
32
+ <Route path="/chat" element={<ProtectedRoute token={token}><Chat /></ProtectedRoute>} />
33
+ <Route path="/analytics" element={<ProtectedRoute token={token}><Analytics /></ProtectedRoute>} />
34
+ <Route path="/models" element={<ProtectedRoute token={token}><DocumentManagement /></ProtectedRoute>} />
35
+ <Route path="/config" element={<ProtectedRoute token={token}><ConfigForm /></ProtectedRoute>} />
36
+ </Routes>
37
+ </div>
38
+ </Router>
39
+ );
40
+ }
41
+
42
+ export default App;
src/assets/react.svg ADDED
src/chartSetup.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {
2
+ Chart as ChartJS,
3
+ CategoryScale,
4
+ LinearScale,
5
+ PointElement,
6
+ LineElement,
7
+ BarElement,
8
+ ArcElement,
9
+ Title,
10
+ Tooltip,
11
+ Legend,
12
+ } from 'chart.js';
13
+
14
+ ChartJS.register(
15
+ CategoryScale,
16
+ LinearScale,
17
+ PointElement,
18
+ LineElement,
19
+ BarElement,
20
+ ArcElement,
21
+ Title,
22
+ Tooltip,
23
+ Legend
24
+ );
25
+
src/components/ChatMessage.jsx ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
+ import { faVolumeUp, faCopy, faSync, faStar, faCogs } from '@fortawesome/free-solid-svg-icons';
4
+
5
+ const ChatMessage = ({ message, isUser }) => {
6
+ return (
7
+ <div className={`flex ${isUser ? 'justify-end' : 'justify-start'} mb-2`}>
8
+ <div className={`flex items-end ${isUser ? 'flex-row-reverse' : 'flex-row'}`}>
9
+ <div className="flex flex-col items-center">
10
+ <div className="w-10 h-10 rounded-full overflow-hidden">
11
+ <img
12
+ src={isUser ? '/public/you.png' : '/public/bot.png'}
13
+ alt={isUser ? 'You' : 'AI Bot'}
14
+ className="w-full h-full object-cover"
15
+ />
16
+ </div>
17
+ <p className="text-xs mt-1">{isUser ? 'You' : 'AI Bot'}</p>
18
+ </div>
19
+ <div className={`p-3 rounded-lg ml-2 max-w-lg ${isUser ? 'bg-blue-600 text-white' : 'bg-gray-300 text-black'}`}>
20
+ <p className="text-sm whitespace-pre-wrap" dangerouslySetInnerHTML={{ __html: message.text }}></p>
21
+ <p className="text-xs mt-1">{message.timestamp}</p>
22
+ {!isUser && (
23
+ <div className="flex mt-2 space-x-2">
24
+ <button className="p-1 text-sm bg-white rounded-full hover:bg-gray-200">
25
+ <FontAwesomeIcon icon={faVolumeUp} />
26
+ </button>
27
+ <button className="p-1 text-sm bg-white rounded-full hover:bg-gray-200">
28
+ <FontAwesomeIcon icon={faCopy} />
29
+ </button>
30
+ <button className="p-1 text-sm bg-white rounded-full hover:bg-gray-200">
31
+ <FontAwesomeIcon icon={faSync} />
32
+ </button>
33
+ <button className="p-1 text-sm bg-white rounded-full hover:bg-gray-200">
34
+ <FontAwesomeIcon icon={faStar} />
35
+ </button>
36
+ <button className="p-1 text-sm bg-white rounded-full hover:bg-gray-200">
37
+ <FontAwesomeIcon icon={faCogs} />
38
+ </button>
39
+ </div>
40
+ )}
41
+ </div>
42
+ </div>
43
+ </div>
44
+ );
45
+ };
46
+
47
+ export default ChatMessage;
src/components/ConfigForm.jsx ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import axios from 'axios';
3
+ import Sidebar from './OCRSidebar';
4
+ import Header from './OCRHeader';
5
+
6
+ const ConfigForm = () => {
7
+ const [config, setConfig] = useState({
8
+ MONGO_DETAILS: '',
9
+ MongoDB_NAME: '',
10
+ COLLECTION_NAMES: '',
11
+ SECRET_KEY: '',
12
+ ALGORITHM: '',
13
+ ACCESS_TOKEN_EXPIRE_MINUTES: 0
14
+ });
15
+
16
+ useEffect(() => {
17
+ axios.get('http://localhost:8000/config')
18
+ .then(response => setConfig(response.data))
19
+ .catch(error => console.error('Error fetching config:', error));
20
+ }, []);
21
+
22
+ const handleChange = (e) => {
23
+ const { name, value } = e.target;
24
+ setConfig({
25
+ ...config,
26
+ [name]: value
27
+ });
28
+ };
29
+
30
+ const handleSubmit = (e) => {
31
+ e.preventDefault();
32
+ axios.patch('http://localhost:8000/config', config)
33
+ .then(response => {
34
+ setConfig(response.data);
35
+ alert('Config updated successfully!');
36
+ })
37
+ .catch(error => console.error('Error updating config:', error));
38
+ };
39
+
40
+ return (
41
+ <div className="min-h-screen bg-gray-100 flex">
42
+ <Sidebar />
43
+ <div className="flex-1 p-6">
44
+ <Header />
45
+ <div className="bg-white p-6 rounded-lg shadow-lg w-full max-w-4xl mx-auto">
46
+ <h2 className="text-2xl font-bold mb-6">Manage Credentials</h2>
47
+ <form className="space-y-4" onSubmit={handleSubmit}>
48
+ <div>
49
+ <label className="block text-gray-700">ERP details</label>
50
+ <input
51
+ type="text"
52
+ name="MONGO_DETAILS"
53
+ value={config.MONGO_DETAILS}
54
+ onChange={handleChange}
55
+ className="w-full px-4 py-2 border rounded-md"
56
+ />
57
+ </div>
58
+ <div>
59
+ <label className="block text-gray-700">Client ID</label>
60
+ <input
61
+ type="text"
62
+ name="MongoDB_NAME"
63
+ value={config.MongoDB_NAME}
64
+ onChange={handleChange}
65
+ className="w-full px-4 py-2 border rounded-md"
66
+ />
67
+ </div>
68
+ <div>
69
+ <label className="block text-gray-700">Client Secret</label>
70
+ <input
71
+ type="text"
72
+ name="COLLECTION_NAMES"
73
+ value={config.COLLECTION_NAMES}
74
+ onChange={handleChange}
75
+ className="w-full px-4 py-2 border rounded-md"
76
+ />
77
+ </div>
78
+ <div>
79
+ <label className="block text-gray-700">Username</label>
80
+ <input
81
+ type="text"
82
+ name="SECRET_KEY"
83
+ value={config.SECRET_KEY}
84
+ onChange={handleChange}
85
+ className="w-full px-4 py-2 border rounded-md"
86
+ />
87
+ </div>
88
+ <div>
89
+ <label className="block text-gray-700">Password</label>
90
+ <input
91
+ type="password"
92
+ name="ALGORITHM"
93
+ value={config.ALGORITHM}
94
+ onChange={handleChange}
95
+ className="w-full px-4 py-2 border rounded-md"
96
+ />
97
+ </div>
98
+ <div>
99
+ <label className="block text-gray-700">Company Code</label>
100
+ <input
101
+ type="text"
102
+ name="ACCESS_TOKEN_EXPIRE_MINUTES"
103
+ value={config.ACCESS_TOKEN_EXPIRE_MINUTES}
104
+ onChange={handleChange}
105
+ className="w-full px-4 py-2 border rounded-md"
106
+ />
107
+ </div>
108
+ <div>
109
+ <label className="block text-gray-700">API Key (Optional)</label>
110
+ <input
111
+ type="text"
112
+ name="API_KEY"
113
+ value={config.API_KEY}
114
+ onChange={handleChange}
115
+ className="w-full px-4 py-2 border rounded-md"
116
+ />
117
+ </div>
118
+ <button
119
+ type="submit"
120
+ className="w-full bg-blue-500 text-white px-4 py-2 rounded-md"
121
+ >
122
+ Save Credentials
123
+ </button>
124
+ </form>
125
+ </div>
126
+ </div>
127
+ </div>
128
+ );
129
+ };
130
+
131
+ export default ConfigForm;
src/components/ERPCredentials.jsx ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState } from 'react';
2
+ import Sidebar from './OCRSidebar';
3
+
4
+ function Credentials({ onSave }) {
5
+ const [credentials, setCredentials] = useState({
6
+ sapUrl: '',
7
+ clientId: '',
8
+ clientSecret: '',
9
+ username: '',
10
+ password: '',
11
+ companyCode: '',
12
+ apiKey: ''
13
+ });
14
+
15
+ const handleChange = (e) => {
16
+ const { name, value } = e.target;
17
+ setCredentials({ ...credentials, [name]: value });
18
+ };
19
+
20
+ const handleSubmit = (e) => {
21
+ e.preventDefault();
22
+ onSave(credentials);
23
+ };
24
+
25
+ return (
26
+ <div className="min-h-screen bg-gray-100 flex">
27
+ <Sidebar />
28
+ <div className="flex-1 p-6">
29
+ <div className="bg-white p-6 rounded-lg shadow-lg w-full max-w-4xl mx-auto">
30
+ <h2 className="text-xl font-semibold text-gray-700 mb-4">Manage Credentials</h2>
31
+ <form onSubmit={handleSubmit}>
32
+ <div className="mb-4">
33
+ <label className="block text-gray-700 text-sm font-bold mb-2">SAP System URL</label>
34
+ <input
35
+ type="text"
36
+ name="sapUrl"
37
+ value={credentials.sapUrl}
38
+ onChange={handleChange}
39
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
40
+ />
41
+ </div>
42
+ <div className="mb-4">
43
+ <label className="block text-gray-700 text-sm font-bold mb-2">Client ID</label>
44
+ <input
45
+ type="text"
46
+ name="clientId"
47
+ value={credentials.clientId}
48
+ onChange={handleChange}
49
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
50
+ />
51
+ </div>
52
+ <div className="mb-4">
53
+ <label className="block text-gray-700 text-sm font-bold mb-2">Client Secret</label>
54
+ <input
55
+ type="text"
56
+ name="clientSecret"
57
+ value={credentials.clientSecret}
58
+ onChange={handleChange}
59
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
60
+ />
61
+ </div>
62
+ <div className="mb-4">
63
+ <label className="block text-gray-700 text-sm font-bold mb-2">Username</label>
64
+ <input
65
+ type="text"
66
+ name="username"
67
+ value={credentials.username}
68
+ onChange={handleChange}
69
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
70
+ />
71
+ </div>
72
+ <div className="mb-4">
73
+ <label className="block text-gray-700 text-sm font-bold mb-2">Password</label>
74
+ <input
75
+ type="password"
76
+ name="password"
77
+ value={credentials.password}
78
+ onChange={handleChange}
79
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
80
+ />
81
+ </div>
82
+ <div className="mb-4">
83
+ <label className="block text-gray-700 text-sm font-bold mb-2">Company Code</label>
84
+ <input
85
+ type="text"
86
+ name="companyCode"
87
+ value={credentials.companyCode}
88
+ onChange={handleChange}
89
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
90
+ />
91
+ </div>
92
+ <div className="mb-4">
93
+ <label className="block text-gray-700 text-sm font-bold mb-2">API Key (Optional)</label>
94
+ <input
95
+ type="text"
96
+ name="apiKey"
97
+ value={credentials.apiKey}
98
+ onChange={handleChange}
99
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
100
+ />
101
+ </div>
102
+ <button type="submit" className="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition duration-200">
103
+ Save Credentials
104
+ </button>
105
+ </form>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ );
110
+ }
111
+
112
+ export default Credentials;
src/components/ForgotPassword.jsx ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from 'react';
2
+ import axios from 'axios';
3
+ import '../styles/ForgotPassword.css';
4
+
5
+ const ForgotPassword = () => {
6
+ const [email, setEmail] = useState('');
7
+
8
+ const handleSubmit = async (e) => {
9
+ e.preventDefault();
10
+ try {
11
+ const response = await axios.post('/api/forgot-password', { email });
12
+ console.log('Response:', response.data);
13
+ alert('Password reset link sent to your email');
14
+ } catch (error) {
15
+ console.error('Failed to send password reset link', error);
16
+ }
17
+ };
18
+
19
+ return (
20
+ <div className="min-h-screen flex items-center justify-center bg-gradient-to-r from-purple-400 via-pink-500 to-blue-500">
21
+ <div className="flex flex-col md:flex-row bg-white rounded-lg shadow-md overflow-hidden w-full max-w-4xl">
22
+ <div className="md:w-1/2 flex justify-center items-center bg-gray-100">
23
+ <img src="/public/HiDigiH.jpg" alt="HiDigi Logo" style={{ height: '250px', width: '250px' }} />
24
+ </div>
25
+ <div className="md:w-1/2 p-8">
26
+ <h2 className="text-2xl font-bold mb-6 text-center">Forgot Password</h2>
27
+ <form onSubmit={handleSubmit}>
28
+ <div className="mb-4">
29
+ <label className="block text-gray-700 mb-2">Email</label>
30
+ <input
31
+ type="email"
32
+ name="email"
33
+ value={email}
34
+ onChange={(e) => setEmail(e.target.value)}
35
+ className="w-full p-3 border border-gray-300 rounded"
36
+ placeholder="Type your email"
37
+ required
38
+ />
39
+ </div>
40
+ <button type="submit" className="w-full bg-blue-500 text-white py-3 px-4 rounded mt-4 hover:bg-blue-600">Send Reset Link</button>
41
+ </form>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ );
46
+ };
47
+
48
+ export default ForgotPassword;
src/components/HomeDashboard.jsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Link } from 'react-router-dom';
2
+
3
+ function HomeDashboard() {
4
+
5
+ return (
6
+ <div className="min-h-screen bg-gray-100 flex flex-col justify-center items-center">
7
+ <h1 className="text-4xl font-bold mb-8">Welcome to the Speech Services Dashboard</h1>
8
+ <div className="flex space-x-4">
9
+ <Link to="/text-to-speech" className="px-6 py-3 bg-blue-500 text-white rounded-lg">Text to Speech</Link>
10
+ <Link to="/speech-to-text" className="px-6 py-3 bg-green-500 text-white rounded-lg">Speech to Text</Link>
11
+ </div>
12
+ </div>
13
+ );
14
+ }
15
+
16
+ export default HomeDashboard;
src/components/InvoiceForm.jsx ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // src/components/InvoiceForm.jsx
2
+ import React, { useState } from 'react';
3
+
4
+ function InvoiceForm ({ onSubmit }) {
5
+ const [invoiceData, setInvoiceData] = useState({
6
+ invoiceNumber: '',
7
+ invoiceDate: '',
8
+ vendorNumber: '',
9
+ vendorName: '',
10
+ poNumber: '',
11
+ poDate: '',
12
+ grDate: '',
13
+ amount: '',
14
+ currency: 'USD',
15
+ paymentTerms: '',
16
+ taxAmount: '',
17
+ taxCode: '',
18
+ description: '',
19
+ costCenter: '',
20
+ glAccount: '',
21
+ lineItems: [
22
+ {
23
+ itemNumber: '',
24
+ description: '',
25
+ quantity: '',
26
+ unitPrice: '',
27
+ totalPrice: ''
28
+ }
29
+ ]
30
+ });
31
+
32
+ const handleChange = (e) => {
33
+ const { name, value } = e.target;
34
+ setInvoiceData({
35
+ ...invoiceData,
36
+ [name]: value
37
+ });
38
+ };
39
+
40
+ const handleLineItemChange = (index, e) => {
41
+ const { name, value } = e.target;
42
+ const newLineItems = [...invoiceData.lineItems];
43
+ newLineItems[index][name] = value;
44
+ setInvoiceData({
45
+ ...invoiceData,
46
+ lineItems: newLineItems
47
+ });
48
+ };
49
+
50
+ const addLineItem = () => {
51
+ setInvoiceData({
52
+ ...invoiceData,
53
+ lineItems: [
54
+ ...invoiceData.lineItems,
55
+ { itemNumber: '', description: '', quantity: '', unitPrice: '', totalPrice: '' }
56
+ ]
57
+ });
58
+ };
59
+
60
+ const handleSubmit = (e) => {
61
+ e.preventDefault();
62
+ onSubmit(invoiceData);
63
+ };
64
+
65
+ return (
66
+ <form onSubmit={handleSubmit}>
67
+ <h2 className="text-xl font-semibold text-gray-700 mb-4">Enter Invoice Data</h2>
68
+ <div className="mb-4">
69
+ <label className="block text-gray-700 text-sm font-bold mb-2">Invoice Number</label>
70
+ <input
71
+ type="text"
72
+ name="invoiceNumber"
73
+ value={invoiceData.invoiceNumber}
74
+ onChange={handleChange}
75
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
76
+ />
77
+ </div>
78
+ {/* Add more fields here following the same pattern */}
79
+ {/* Vendor Information */}
80
+ {/* Purchase Order Information */}
81
+ {/* Goods Receipt Date, Amount, etc. */}
82
+ <div className="mb-4">
83
+ <label className="block text-gray-700 text-sm font-bold mb-2">Line Items</label>
84
+ {invoiceData.lineItems.map((item, index) => (
85
+ <div key={index} className="mb-2">
86
+ <label className="block text-gray-700 text-sm font-bold mb-2">Item {index + 1}</label>
87
+ <input
88
+ type="text"
89
+ name="description"
90
+ value={item.description}
91
+ onChange={(e) => handleLineItemChange(index, e)}
92
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 mb-2"
93
+ placeholder="Description"
94
+ />
95
+ <input
96
+ type="text"
97
+ name="quantity"
98
+ value={item.quantity}
99
+ onChange={(e) => handleLineItemChange(index, e)}
100
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 mb-2"
101
+ placeholder="Quantity"
102
+ />
103
+ <input
104
+ type="text"
105
+ name="unitPrice"
106
+ value={item.unitPrice}
107
+ onChange={(e) => handleLineItemChange(index, e)}
108
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 mb-2"
109
+ placeholder="Unit Price"
110
+ />
111
+ <input
112
+ type="text"
113
+ name="totalPrice"
114
+ value={item.totalPrice}
115
+ onChange={(e) => handleLineItemChange(index, e)}
116
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
117
+ placeholder="Total Price"
118
+ />
119
+ </div>
120
+ ))}
121
+ <button type="button" onClick={addLineItem} className="bg-blue-500 text-white py-2 px-4 rounded-lg hover:bg-blue-600 transition duration-200">
122
+ Add Line Item
123
+ </button>
124
+ </div>
125
+ <button type="submit" className="w-full bg-green-500 text-white py-2 rounded-lg hover:bg-green-600 transition duration-200">
126
+ Submit Invoice
127
+ </button>
128
+ </form>
129
+ );
130
+ };
131
+
132
+ export default InvoiceForm;
src/components/Login.jsx ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import axios from 'axios';
2
+ import { useState } from 'react';
3
+ import { useNavigate } from 'react-router-dom';
4
+ import { login } from '../services/api';
5
+ import '../styles/Login.css';
6
+
7
+ axios.defaults.withCredentials = true;
8
+
9
+ function Login() {
10
+ const [formData, setFormData] = useState({
11
+ usernameOrEmail: '',
12
+ password: '',
13
+ });
14
+ const navigate = useNavigate();
15
+
16
+ const handleChange = (e) => {
17
+ setFormData({ ...formData, [e.target.name]: e.target.value });
18
+ };
19
+
20
+ const handleSubmit = async (e) => {
21
+ e.preventDefault();
22
+ const { usernameOrEmail, password } = formData;
23
+ try {
24
+ const response = await login(usernameOrEmail, password);
25
+ console.log(response.data);
26
+ localStorage.setItem('token', response.data["access_token"]);
27
+ console.log('Token stored in localStorage:', localStorage.getItem('token'));
28
+ navigate('/ocrdashboard');
29
+ } catch (error) {
30
+ console.error('Login failed', error);
31
+ }
32
+ };
33
+
34
+ return (
35
+ <div className="min-h-screen flex items-center justify-center bg-gradient-to-r from-purple-400 via-pink-500 to-blue-500">
36
+ <div className="flex flex-col md:flex-row bg-white rounded-lg shadow-md overflow-hidden w-full max-w-4xl">
37
+ <div className="md:w-1/2 flex justify-center items-center bg-gray-100">
38
+ <img src="/public/HiDigiH.jpg" alt="HiDigi Logo" style={{ height: '250px', width: '250px' }} />
39
+ </div>
40
+ <div className="md:w-1/2 p-8">
41
+ <h2 className="text-2xl font-bold mb-6 text-center">Sign in</h2>
42
+ <form onSubmit={handleSubmit}>
43
+ <div className="mb-4">
44
+ <label className="block text-gray-700 mb-2">Username or Email</label>
45
+ <input
46
+ type="text"
47
+ name="usernameOrEmail"
48
+ value={formData.usernameOrEmail}
49
+ onChange={handleChange}
50
+ className="w-full p-3 border border-gray-300 rounded"
51
+ placeholder="Type your username or email"
52
+ required
53
+ />
54
+ </div>
55
+ <div className="mb-4">
56
+ <label className="block text-gray-700 mb-2">Password</label>
57
+ <input
58
+ type="password"
59
+ name="password"
60
+ value={formData.password}
61
+ onChange={handleChange}
62
+ className="w-full p-3 border border-gray-300 rounded"
63
+ placeholder="Type your password"
64
+ required
65
+ />
66
+ <div className="text-right mt-2">
67
+ <a href="/forgot-password" className="text-blue-500 hover:underline">Forgot Password?</a>
68
+ </div>
69
+ </div>
70
+ <button type="submit" className="w-full bg-blue-500 text-white py-3 px-4 rounded mt-4 hover:bg-blue-600">Sign in</button>
71
+ </form>
72
+ <div className="text-center text-gray-500 text-sm mt-6">
73
+ By clicking "Sign in", you agree to our <a href="/terms" className="text-blue-500 hover:underline">Terms and Conditions</a> and <a href="/privacy" className="text-blue-500 hover:underline">Privacy Policy</a>.
74
+ </div>
75
+ <div className="text-center text-gray-500 text-sm mt-4">
76
+ Don't have an account? <a href="/register" className="text-blue-500 hover:underline">Register</a>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ );
82
+ }
83
+
84
+ export default Login;
src/components/Logout.jsx ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useEffect } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+
4
+ function Logout() {
5
+ const navigate = useNavigate();
6
+
7
+ useEffect(() => {
8
+ const handleLogout = () => {
9
+ // Clear any stored user data (e.g., tokens) here
10
+ localStorage.removeItem('token'); // Example, adjust based on your implementation
11
+ navigate('/login');
12
+ };
13
+
14
+ handleLogout();
15
+ }, [navigate]);
16
+
17
+ return null; // Or a loading spinner/message if desired
18
+ }
19
+
20
+ export default Logout;
src/components/OCRDashboard.jsx ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import Sidebar from './OCRSidebar';
3
+ import Header from './OCRHeader';
4
+ import { getTemplates, ocrProcess } from '../services/api';
5
+ import Quota from './OCRQuota';
6
+ import OCRTemplate from './OCRTemplate';
7
+ import Credentials from './ERPCredentials';
8
+ import InvoiceForm from './InvoiceForm';
9
+
10
+ const Dashboard = () => {
11
+ const [selectedFiles, setSelectedFiles] = useState([]);
12
+ const [templates, setTemplates] = useState([]); // Ensure templates is initialized as an array
13
+ const [selectedTemplate, setSelectedTemplate] = useState('');
14
+ const [credentials, setCredentials] = useState({
15
+ sapUrl: '',
16
+ clientId: '',
17
+ clientSecret: '',
18
+ username: '',
19
+ password: '',
20
+ companyCode: '',
21
+ apiKey: ''
22
+ });
23
+
24
+ const fetchTemplates = async (templateName = false) => {
25
+ try {
26
+ const response = await getTemplates(templateName);
27
+ setTemplates(response); // Ensure response is directly set to templates
28
+ } catch (error) {
29
+ console.error('Error fetching templates:', error);
30
+ }
31
+ };
32
+
33
+ const handleFolderSelect = (event) => {
34
+ const files = Array.from(event.target.files);
35
+ const validFileTypes = ['application/pdf', 'image/png', 'image/jpeg', 'image/jpg', 'image/PNG', 'image/JPEG'];
36
+ const filteredFiles = files.filter(file => validFileTypes.includes(file.type));
37
+ setSelectedFiles(filteredFiles);
38
+ };
39
+
40
+ const handleTemplateChange = (event) => {
41
+ const newValue = event.target.value;
42
+ setSelectedTemplate(newValue);
43
+ console.log("selectedTemplate:", newValue);
44
+ // Fetch templates based on the selected template
45
+ };
46
+
47
+ const handleCredentialsSave = (newCredentials) => {
48
+ setCredentials(newCredentials);
49
+ };
50
+
51
+ const handleSubmit = async (event) => {
52
+ event.preventDefault(); // Prevent default form submission behavior
53
+
54
+ if (selectedFiles.length === 0) {
55
+ alert("Please select files containing PDF, PNG, or JPG files.");
56
+ return;
57
+ }
58
+
59
+ if (!selectedTemplate) {
60
+ alert("Please select a template.");
61
+ return;
62
+ }
63
+
64
+ const formData = new FormData();
65
+ selectedFiles.forEach(file => formData.append("files", file));
66
+ formData.append("template_name", selectedTemplate);
67
+
68
+ // Debugging formData
69
+ for (let [key, value] of formData.entries()) {
70
+ console.log(`${key}: ${value.name || value}`);
71
+ }
72
+
73
+ try {
74
+ const response = await ocrProcess(formData);
75
+ console.log("Response:", response);
76
+ alert("Files processed successfully!");
77
+ } catch (error) {
78
+ console.error("Error:", error);
79
+ alert("There was an error processing the files.");
80
+ }
81
+ };
82
+
83
+ // Fetch templates on component mount
84
+ useEffect(() => {
85
+ fetchTemplates();
86
+ }, []);
87
+
88
+ return (
89
+ <div className="min-h-screen bg-gray-100 flex">
90
+ <Sidebar />
91
+ <div className="flex-1 p-6">
92
+ <Header />
93
+ <div className="bg-white p-6 rounded-lg shadow-lg w-full max-w-4xl mx-auto">
94
+ <h1 className="text-2xl font-semibold text-gray-700 mb-4">Automate Data Input & OCR</h1>
95
+ <p className="text-gray-600 mb-4">
96
+ AI services that allow you to extract information from any documents and automate data input to external applications.
97
+ </p>
98
+ <div className="border-t border-gray-200 pt-4">
99
+ <h2 className="text-xl font-semibold text-gray-700 mb-4">Upload PDF Folder</h2>
100
+ <div className="mb-4">
101
+ <input
102
+ type="file"
103
+ // webkitdirectory="true"
104
+ // mozdirectory="true"
105
+ // directory=""
106
+ onChange={handleFolderSelect}
107
+ multiple
108
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
109
+ />
110
+ </div>
111
+ {selectedFiles.length > 0 && (
112
+ <div className="mb-4">
113
+ <h3 className="text-lg font-semibold text-gray-700">Detected PDF Files:</h3>
114
+ <ul className="list-disc pl-5">
115
+ {selectedFiles.map((file, index) => (
116
+ <li key={index} className="text-gray-600">{file.name}</li>
117
+ ))}
118
+ </ul>
119
+ </div>
120
+ )}
121
+ <div className="mb-4">
122
+ <label className="block text-gray-700 text-sm font-bold mb-2">Select Template</label>
123
+ <select
124
+ value={selectedTemplate}
125
+ onChange={handleTemplateChange}
126
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600"
127
+ >
128
+ <option value="">Select a template</option>
129
+ {templates.map((template, index) => (
130
+ <option key={index} value={template.template_name}>{template.template_name}</option>
131
+ ))}
132
+ </select>
133
+ </div>
134
+ <button
135
+ onClick={handleSubmit}
136
+ className="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition duration-200 mb-4"
137
+ >
138
+ Process Files
139
+ </button>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ );
145
+ };
146
+
147
+ export default Dashboard;
src/components/OCRHeader.jsx ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // src/components/Header.jsx
2
+ import React from 'react';
3
+
4
+ function Header() {
5
+ return (
6
+ <div className="flex justify-between items-center mb-4">
7
+ <h1 className="text-2xl font-semibold text-gray-700">OCR Dashboard</h1>
8
+ <div className="flex space-x-4">
9
+ <button className="bg-blue-500 text-white py-2 px-4 rounded-lg hover:bg-blue-600 transition duration-200">
10
+ Contact us
11
+ </button>
12
+ <button className="bg-green-500 text-white py-2 px-4 rounded-lg hover:bg-green-600 transition duration-200">
13
+ Get Your Free Trial
14
+ </button>
15
+ </div>
16
+ </div>
17
+ );
18
+ };
19
+
20
+ export default Header;
src/components/OCRQuota.jsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // src/components/Quota.jsx
2
+ import React from 'react';
3
+
4
+ function Quota() {
5
+ return (
6
+ <div className="border-t border-gray-200 pt-4">
7
+ <h2 className="text-xl font-semibold text-gray-700">Your Quota Remaining</h2>
8
+ <div className="flex items-center space-x-2 mb-4">
9
+ <span className="text-4xl font-bold text-gray-800">0</span>
10
+ <span className="text-gray-600">times</span>
11
+ </div>
12
+ </div>
13
+ );
14
+ };
15
+
16
+ export default Quota;
src/components/OCRSidebar.jsx ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { Link, useNavigate } from 'react-router-dom';
3
+ import { DocumentTextIcon, KeyIcon, ChartBarIcon, ClipboardListIcon, CogIcon, LogoutIcon, TemplateIcon } from '@heroicons/react/outline';
4
+
5
+ function Sidebar() {
6
+ const navigate = useNavigate();
7
+
8
+ const handleLogout = () => {
9
+ // Clear any stored user data (e.g., tokens) here
10
+ localStorage.removeItem('token'); // Example, adjust based on your implementation
11
+ navigate('/login');
12
+ };
13
+
14
+ return (
15
+ <div className="bg-gray-800 text-white w-64 p-4 space-y-6">
16
+ <h2 className="text-2xl font-bold">HiDigi</h2>
17
+ <nav>
18
+ <ul className="space-y-4">
19
+ <li className="hover:bg-gray-700 p-2 rounded-lg">
20
+ <Link to="/ocrdashboard" className="flex items-center space-x-2">
21
+ <DocumentTextIcon className="h-6 w-6" />
22
+ <span>Home</span>
23
+ </Link>
24
+ </li>
25
+ <li className="hover:bg-gray-700 p-2 rounded-lg">
26
+ <Link to="/ocrtemplate" className="flex items-center space-x-2">
27
+ <TemplateIcon className="h-6 w-6" />
28
+ <span>Application Template</span>
29
+ </Link>
30
+ </li>
31
+ <li className="hover:bg-gray-700 p-2 rounded-lg">
32
+ <Link to="/erpcredential" className="flex items-center space-x-2">
33
+ <KeyIcon className="h-6 w-6" />
34
+ <span>Manage Credentials</span>
35
+ </Link>
36
+ </li>
37
+ <li className="hover:bg-gray-700 p-2 rounded-lg">
38
+ <Link to="/summary" className="flex items-center space-x-2">
39
+ <ChartBarIcon className="h-6 w-6" />
40
+ <span>Summary</span>
41
+ </Link>
42
+ </li>
43
+ <li className="hover:bg-gray-700 p-2 rounded-lg">
44
+ <Link to="/transaction-detail" className="flex items-center space-x-2">
45
+ <ClipboardListIcon className="h-6 w-6" />
46
+ <span>Transaction Detail</span>
47
+ </Link>
48
+ </li>
49
+ <li className="hover:bg-gray-700 p-2 rounded-lg">
50
+ <Link to="/settings" className="flex items-center space-x-2">
51
+ <CogIcon className="h-6 w-6" />
52
+ <span>Settings</span>
53
+ </Link>
54
+ </li>
55
+ <li className="hover:bg-gray-700 p-2 rounded-lg">
56
+ <Link to="/logout" className="flex items-center space-x-2">
57
+ <LogoutIcon className="h-6 w-6" />
58
+ <span>Logout</span>
59
+ </Link>
60
+ </li>
61
+ </ul>
62
+ </nav>
63
+ </div>
64
+ );
65
+ }
66
+
67
+ export default Sidebar;
src/components/OCRTemplate.jsx ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import Sidebar from './OCRSidebar';
3
+ import { createTemplate, getTemplates, deleteTemplate, createOrUpdateTemplate } from '../services/api';
4
+
5
+ function OCRTemplate() {
6
+ const [templates, setTemplates] = useState([]);
7
+ const [selectedTemplate, setSelectedTemplate] = useState(null);
8
+ const [newTemplateName, setNewTemplateName] = useState('');
9
+ const [isEditing, setIsEditing] = useState(false);
10
+ const [message, setMessage] = useState('');
11
+
12
+ const fetchTemplates = async () => {
13
+ try {
14
+ const response = await getTemplates();
15
+ console.log('fetchTemplates Response:', response);
16
+ const mappedTemplates = response.map(template => ({
17
+ template_name: template.template_name,
18
+ variables: Object.values(template.fields || {}), // Map fields to variables
19
+ user_id: template.user_id,
20
+ }));
21
+ setTemplates(mappedTemplates);
22
+ } catch (error) {
23
+ console.error('Error fetching templates:', error);
24
+ }
25
+ };
26
+ const handleTemplateChange = (e) => {
27
+ const templateName = e.target.value;
28
+ if (templateName === 'new') {
29
+ setSelectedTemplate(null);
30
+ setNewTemplateName('');
31
+ setIsEditing(false);
32
+ } else {
33
+
34
+ const existingTemplate = templates.find(template => template.template_name === templateName);
35
+ setSelectedTemplate(existingTemplate || null);
36
+ setIsEditing(!!existingTemplate);
37
+
38
+ }
39
+ };
40
+
41
+
42
+
43
+ const addVariable = () => {
44
+ const newTemplate = { ...selectedTemplate, variables: [...(selectedTemplate.variables || []), ''] };
45
+ setSelectedTemplate(newTemplate);
46
+ };
47
+
48
+ const handleTemplateNameChange = (value) => {
49
+ const newTemplate = { ...selectedTemplate, template_name: value };
50
+ setSelectedTemplate(newTemplate);
51
+ };
52
+
53
+ const handleVariableChange = (variableIndex, value) => {
54
+ const newTemplate = { ...selectedTemplate };
55
+ newTemplate.variables[variableIndex] = value;
56
+ setSelectedTemplate(newTemplate);
57
+ };
58
+
59
+ const addTemplate = () => {
60
+ const newTemplate = { template_name: newTemplateName, variables: [''] };
61
+ // setTemplates([...templates, newTemplate]);
62
+ setSelectedTemplate(newTemplate);
63
+ setIsEditing(true);
64
+ };
65
+
66
+ const handleSubmit = async () => {
67
+ const template = selectedTemplate;
68
+ const fields = {};
69
+ template.variables.forEach((variable, i) => {
70
+ fields[`additionalProp${i + 1}`] = variable;
71
+ });
72
+
73
+ try {
74
+ console.log(template);
75
+ // Check if the template name already exists
76
+ const existingTemplate = templates.find(t => t.template_name === template.template_name);
77
+
78
+
79
+
80
+ if (existingTemplate) {
81
+ // Update existing template
82
+ console.log('existingTemplate', existingTemplate.template_name);
83
+ await createOrUpdateTemplate(template.template_name, fields, template.user_id, true);
84
+ setMessage('Template updated successfully!');
85
+ } else {
86
+ console.log('Creating new template');
87
+ // Create new template
88
+ const newTemplate = await createOrUpdateTemplate(template.template_name, fields, template.user_id, false);
89
+
90
+ setMessage('Template created successfully!');
91
+ }
92
+ fetchTemplates(); // Fetch templates again to update the list
93
+ } catch (error) {
94
+ setMessage('Handle submit Error creating/updating template.');
95
+ }
96
+ };
97
+
98
+ const handleDeleteTemplate = async () => {
99
+ const templateName = selectedTemplate.template_name;
100
+ try {
101
+ await deleteTemplate(templateName);
102
+ setTemplates(templates.filter(template => template.template_name !== templateName));
103
+ setSelectedTemplate(null);
104
+ setMessage('Template deleted successfully!');
105
+ } catch (error) {
106
+ setMessage('Error deleting template.');
107
+ }
108
+ };
109
+
110
+ const handleDeleteVariable = (variableIndex) => {
111
+ const newTemplate = { ...selectedTemplate };
112
+ newTemplate.variables.splice(variableIndex, 1);
113
+ setSelectedTemplate(newTemplate);
114
+ };
115
+
116
+ // Fetch templates on component mount
117
+ useEffect(() => {
118
+ fetchTemplates();
119
+ }, []);
120
+
121
+ return (
122
+ <div className="min-h-screen bg-gray-100 flex">
123
+ <Sidebar />
124
+ <div className="flex-1 p-6">
125
+ <div className="bg-white p-6 rounded-lg shadow-lg w-full max-w-4xl mx-auto">
126
+ <h2 className="text-xl font-semibold text-gray-700">Application Template</h2>
127
+ <div className="mb-4">
128
+ <label className="block text-gray-700 text-sm font-bold mb-2">Select Template</label>
129
+ <select
130
+ value={selectedTemplate ? selectedTemplate.template_name : 'new'}
131
+ onChange={handleTemplateChange}
132
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 mb-2"
133
+ >
134
+ <option value="new">Create New Template</option>
135
+ {templates.map((template, index) => (
136
+ <option key={index} value={template.template_name}>{template.template_name}</option>
137
+ ))}
138
+ </select>
139
+ </div>
140
+ {!selectedTemplate && (
141
+ <div className="mb-4">
142
+ <label className="block text-gray-700 text-sm font-bold mb-2">Template Name</label>
143
+ <input
144
+ type="text"
145
+ value={newTemplateName}
146
+ onChange={(e) => setNewTemplateName(e.target.value)}
147
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 mb-2"
148
+ />
149
+ <button
150
+ onClick={addTemplate}
151
+ className="bg-green-500 text-white py-2 px-4 rounded-lg hover:bg-green-600 transition duration-200"
152
+ >
153
+ Add Template
154
+ </button>
155
+ </div>
156
+ )}
157
+ {selectedTemplate && (
158
+ <div className="mb-4">
159
+ <label className="block text-gray-700 text-sm font-bold mb-2">Template Name</label>
160
+ <input
161
+ type="text"
162
+ value={selectedTemplate.template_name}
163
+ onChange={(e) => handleTemplateNameChange(e.target.value)}
164
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 mb-2"
165
+ />
166
+ {selectedTemplate.variables.map((variable, varIndex) => (
167
+ <div key={varIndex} className="mb-2 flex items-center">
168
+ <label className="block text-gray-700 text-sm font-bold mb-2">Variable {varIndex + 1}</label>
169
+ <input
170
+ type="text"
171
+ value={variable}
172
+ onChange={(e) => handleVariableChange(varIndex, e.target.value)}
173
+ className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-600 mx-2"
174
+ />
175
+ <button
176
+ onClick={() => handleDeleteVariable(varIndex)}
177
+ className="bg-red-500 text-white py-2 px-4 rounded-lg hover:bg-red-600 transition duration-200"
178
+ >
179
+ Delete Variable
180
+ </button>
181
+ </div>
182
+ ))}
183
+ <div className="flex items-center">
184
+ <button
185
+ onClick={addVariable}
186
+ className="bg-blue-500 text-white py-2 px-4 rounded-lg hover:bg-blue-600 transition duration-200 mr-2"
187
+ >
188
+ Add Variable
189
+ </button>
190
+ <button
191
+ onClick={handleSubmit}
192
+ className="bg-green-500 text-white py-2 px-4 rounded-lg hover:bg-green-600 transition duration-200 mr-2"
193
+ >
194
+ Submit Template
195
+ </button>
196
+ <button
197
+ onClick={handleDeleteTemplate}
198
+ className="bg-red-500 text-white py-2 px-4 rounded-lg hover:bg-red-600 transition duration-200"
199
+ >
200
+ Delete Template
201
+ </button>
202
+ </div>
203
+ </div>
204
+ )}
205
+ {message && <p className="mt-4 text-gray-700">{message}</p>}
206
+ </div>
207
+ </div>
208
+ </div>
209
+ );
210
+ }
211
+
212
+ export default OCRTemplate;
src/components/PrivacyPolicy.jsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import '../styles/PrivacyPolicy.css';
2
+
3
+ const PrivacyPolicy = () => {
4
+ return (
5
+ <div className="min-h-screen flex items-center justify-center bg-gradient-to-r from-purple-400 via-pink-500 to-blue-500">
6
+ <div className="bg-white p-8 rounded-lg shadow-md w-full max-w-4xl">
7
+ <h2 className="text-2xl font-bold mb-6 text-center">Privacy Policy</h2>
8
+ <p className="text-gray-700">
9
+ // Insert your privacy policy content here.
10
+ </p>
11
+ </div>
12
+ </div>
13
+ );
14
+ };
15
+
16
+ export default PrivacyPolicy;
src/components/ProtectedRoute.jsx ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Navigate } from 'react-router-dom';
2
+ import {jwtDecode} from 'jwt-decode';
3
+
4
+ const getCookie = (name) => {
5
+ const cookies = document.cookie.split(';');
6
+ console.log(cookies);
7
+ for (let cookie of cookies) {
8
+ const [key, value] = cookie.trim().split('=');
9
+ if (key === name) {
10
+ return value;
11
+ }
12
+ }
13
+ return null;
14
+ };
15
+
16
+ const isTokenValid = (token) => {
17
+ try {
18
+ const decodedToken = jwtDecode(token);
19
+ const currentTime = Date.now() / 1000;
20
+ if (decodedToken.exp < currentTime) {
21
+ return false;
22
+ }
23
+ return true;
24
+ } catch (error) {
25
+ return false;
26
+ }
27
+ };
28
+ function ProtectedRoute({ children }) {
29
+ // const token = getCookie('access-token');
30
+ const token = localStorage.getItem('token');
31
+
32
+ if (!token || !isTokenValid(token)) {
33
+ return <Navigate to="/login" />;
34
+ }
35
+
36
+ return children;
37
+ }
38
+
39
+ export default ProtectedRoute;
src/components/Register.jsx ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import axios from 'axios';
4
+ import '../styles/Register.css';
5
+ import { register } from '../services/api';
6
+
7
+ const API_URL = import.meta.env.VITE_API_URL;
8
+
9
+ const Register = () => {
10
+ const [formData, setFormData] = useState({
11
+ first_name: '',
12
+ surname: '',
13
+ email: '',
14
+ phone: '',
15
+ country: '',
16
+ address: '',
17
+ password: '',
18
+ confirm_password: ''
19
+ });
20
+ const [error, setError] = useState(null);
21
+
22
+ const navigate = useNavigate();
23
+
24
+ const handleChange = (e) => {
25
+ setFormData({ ...formData, [e.target.name]: e.target.value });
26
+ };
27
+
28
+ const handleSubmit = async (e) => {
29
+ e.preventDefault();
30
+ const { first_name, surname, email, phone, country, address, password, confirm_password } = formData;
31
+
32
+ if (password !== confirm_password) {
33
+ setError('Passwords do not match');
34
+ return;
35
+ }
36
+ try {
37
+ console.log('Form Data:', formData);
38
+ const response = await register(first_name, surname, email, phone, country, address, password);
39
+ // const response = await axios.post(`${API_URL}/api/v1/user/`, formData);
40
+ console.log('Response:', response.data);
41
+ navigate('/login');
42
+ } catch (error) {
43
+ console.error('Registration failed', error);
44
+ if (error.response && error.response.status === 400) {
45
+ setError(error.response.data.detail || 'Registration failed');
46
+ } else {
47
+ setError('An unexpected error occurred');
48
+ }
49
+ }
50
+ };
51
+
52
+ return (
53
+ <div className="min-h-screen flex items-center justify-center bg-gradient-to-r from-purple-400 via-pink-500 to-blue-500">
54
+ <div className="flex flex-col md:flex-row bg-white rounded-lg shadow-md overflow-hidden w-full max-w-7xl">
55
+ <div className="md:w-1/2 flex justify-center items-center bg-gray-100">
56
+ <img src="/public/HiDigiH.jpg" alt="HiDigi Logo" style={{ height: '250px', width: '250px' }} />
57
+ </div>
58
+ <div className="md:w-1/2 p-8">
59
+ <h2 className="text-2xl font-bold mb-6 text-center">Sign Up</h2>
60
+ <form onSubmit={handleSubmit}>
61
+ {error && <div className="mb-4 text-center text-red-500">{error}</div>}
62
+ <div className="grid grid-cols-2 gap-4">
63
+ <div className="mb-4">
64
+ <label className="block text-gray-700 mb-2">First Name</label>
65
+ <input
66
+ type="text"
67
+ name="first_name"
68
+ value={formData.first_name}
69
+ onChange={handleChange}
70
+ className="w-full p-3 border border-gray-300 rounded"
71
+ placeholder="First Name"
72
+ required
73
+ />
74
+ </div>
75
+ <div className="mb-4">
76
+ <label className="block text-gray-700 mb-2">Surname</label>
77
+ <input
78
+ type="text"
79
+ name="surname"
80
+ value={formData.surname}
81
+ onChange={handleChange}
82
+ className="w-full p-3 border border-gray-300 rounded"
83
+ placeholder="Surname"
84
+ required
85
+ />
86
+ </div>
87
+ <div className="mb-4">
88
+ <label className="block text-gray-700 mb-2">Phone Number</label>
89
+ <input
90
+ type="text"
91
+ name="phone"
92
+ value={formData.phone}
93
+ onChange={handleChange}
94
+ className="w-full p-3 border border-gray-300 rounded"
95
+ placeholder="Phone Number"
96
+ required
97
+ />
98
+ </div>
99
+ <div className="mb-4">
100
+ <label className="block text-gray-700 mb-2">Country</label>
101
+ <input
102
+ type="text"
103
+ name="country"
104
+ value={formData.country}
105
+ onChange={handleChange}
106
+ className="w-full p-3 border border-gray-300 rounded"
107
+ placeholder="Country"
108
+ required
109
+ />
110
+ </div>
111
+ <div className="mb-4">
112
+ <label className="block text-gray-700 mb-2">Address</label>
113
+ <input
114
+ type="text"
115
+ name="address"
116
+ value={formData.address}
117
+ onChange={handleChange}
118
+ className="w-full p-3 border border-gray-300 rounded"
119
+ placeholder="Address"
120
+ required
121
+ />
122
+ </div>
123
+ <div className="mb-4">
124
+ <label className="block text-gray-700 mb-2">E-Mail</label>
125
+ <input
126
+ type="email"
127
+ name="email"
128
+ value={formData.email}
129
+ onChange={handleChange}
130
+ className="w-full p-3 border border-gray-300 rounded"
131
+ placeholder="E-Mail"
132
+ required
133
+ />
134
+ </div>
135
+ <div className="mb-4">
136
+ <label className="block text-gray-700 mb-2">Password</label>
137
+ <input
138
+ type="password"
139
+ name="password"
140
+ value={formData.password}
141
+ onChange={handleChange}
142
+ className="w-full p-3 border border-gray-300 rounded"
143
+ placeholder="Password"
144
+ required
145
+ />
146
+ </div>
147
+ <div className="mb-4">
148
+ <label className="block text-gray-700 mb-2">Confirm Password</label>
149
+ <input
150
+ type="password"
151
+ name="confirm_password"
152
+ value={formData.confirm_password}
153
+ onChange={handleChange}
154
+ className="w-full p-3 border border-gray-300 rounded"
155
+ placeholder="Confirm Password"
156
+ required
157
+ />
158
+ </div>
159
+ </div>
160
+ <button type="submit" className="w-full bg-blue-500 text-white py-3 px-4 rounded mt-4 hover:bg-blue-600">Register</button>
161
+ </form>
162
+ <div className="text-center text-gray-500 text-sm mt-6">
163
+ Already have an account? <a href="/login" className="text-blue-500 hover:underline">Sign in</a>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+ );
169
+ };
170
+
171
+ export default Register;
src/components/SideBarGPT.jsx ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { Link } from 'react-router-dom';
3
+
4
+ const Sidebar = () => {
5
+ return (
6
+ <div className="h-screen w-64 bg-gray-800 text-white flex flex-col fixed">
7
+ <div className="p-4 text-2xl font-bold">Dashboard</div>
8
+ <nav className="mt-4 flex flex-col space-y-2">
9
+ <Link to="/" className="px-4 py-2 hover:bg-gray-700">Chat</Link>
10
+ <Link to="/analytics" className="px-4 py-2 hover:bg-gray-700">Analytics</Link>
11
+ <Link to="/models" className="px-4 py-2 hover:bg-gray-700">Models</Link>
12
+ <Link to="/settings" className="px-4 py-2 hover:bg-gray-700">Settings</Link>
13
+ </nav>
14
+ </div>
15
+ );
16
+ };
17
+
18
+ export default Sidebar;
src/components/Terms.jsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import '../styles/Terms.css';
2
+
3
+ const Terms = () => {
4
+ return (
5
+ <div className="min-h-screen flex items-center justify-center bg-gradient-to-r from-purple-400 via-pink-500 to-blue-500">
6
+ <div className="bg-white p-8 rounded-lg shadow-md w-full max-w-4xl">
7
+ <h2 className="text-2xl font-bold mb-6 text-center">Terms and Conditions</h2>
8
+ <p className="text-gray-700">
9
+ // Insert your terms and conditions content here.
10
+ </p>
11
+ </div>
12
+ </div>
13
+ );
14
+ };
15
+
16
+ export default Terms;
src/components/TextToSpeech.jsx ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from 'react';
2
+ import { textToSpeech } from '../services/api';
3
+ import languageVoices from '../data/languageVoices'; // Adjust the path as needed
4
+
5
+
6
+ function TextToSpeech() {
7
+ const [text, setText] = useState('');
8
+ const [languageCode, setLanguageCode] = useState('en-US');
9
+ const [ssmlGender, setSsmlGender] = useState('NEUTRAL');
10
+ const [name, setName] = useState('en-US-Standard-C');
11
+ const [pitch, setPitch] = useState(0.0);
12
+ const [speakingRate, setSpeakingRate] = useState(1.0);
13
+ const [volumeGainDb, setVolumeGainDb] = useState(0.0);
14
+ const [audioUrl, setAudioUrl] = useState(null);
15
+ // Ensure you have VITE_API_URL set in your .env file
16
+ const API_URL = import.meta.env.VITE_API_URL;
17
+ const handleTextToSpeech = async () => {
18
+ // Call text-to-speech service
19
+ try {
20
+ const response = await textToSpeech(text, languageCode, ssmlGender, name, pitch, speakingRate, volumeGainDb);
21
+
22
+ const baseUrl = new URL(API_URL);
23
+ const audioUrl = `${baseUrl.origin}/static/storage/audio/${response}`;
24
+ console.log(audioUrl)
25
+ setAudioUrl(audioUrl);
26
+ } catch (error) {
27
+ console.error('Text-to-Speech failed:', error);
28
+ }
29
+ };
30
+
31
+ const handleDeleteAudio = () => {
32
+ setAudioUrl(null);
33
+ };
34
+ return (
35
+ <div className="flex justify-center items-center min-h-screen bg-gray-100 p-4">
36
+ <div className="w-full max-w-3xl p-6 bg-white rounded-lg shadow-md">
37
+ <h2 className="text-3xl font-bold mb-6 text-center text-blue-500">Text-to-Speech AI</h2>
38
+
39
+ <div className="mb-6">
40
+ <textarea
41
+ value={text}
42
+ onChange={(e) => setText(e.target.value)}
43
+ className="w-full h-32 p-3 border rounded"
44
+ placeholder="Enter some text here..."
45
+ />
46
+ </div>
47
+
48
+ <div className="mb-4">
49
+ <label className="block text-gray-700 font-bold mb-2">Volume</label>
50
+ <input
51
+ type="range"
52
+ min="-96.0"
53
+ max="16.0"
54
+ step="0.1"
55
+ value={volumeGainDb}
56
+ onChange={(e) => setVolumeGainDb(parseFloat(e.target.value))}
57
+ className="w-full"
58
+ />
59
+ <span className="block text-right text-gray-600">{volumeGainDb.toFixed(1)}</span>
60
+ </div>
61
+
62
+ <div className="mb-4">
63
+ <label className="block text-gray-700 font-bold mb-2">Rate</label>
64
+ <input
65
+ type="range"
66
+ min="0.25"
67
+ max="4.0"
68
+ step="0.01"
69
+ value={speakingRate}
70
+ onChange={(e) => setSpeakingRate(parseFloat(e.target.value))}
71
+ className="w-full"
72
+ />
73
+ <span className="block text-right text-gray-600">{speakingRate.toFixed(2)}</span>
74
+ </div>
75
+
76
+ <div className="mb-4">
77
+ <label className="block text-gray-700 font-bold mb-2">Pitch</label>
78
+ <input
79
+ type="range"
80
+ min="-20.0"
81
+ max="20.0"
82
+ step="0.1"
83
+ value={pitch}
84
+ onChange={(e) => setPitch(parseFloat(e.target.value))}
85
+ className="w-full"
86
+ />
87
+ <span className="block text-right text-gray-600">{pitch.toFixed(1)}</span>
88
+ </div>
89
+
90
+ <div className="mb-4">
91
+ <label className="block text-gray-700 font-bold mb-2">Language</label>
92
+ <select
93
+ value={languageCode}
94
+ onChange={(e) => {
95
+ setLanguageCode(e.target.value);
96
+ setName(languageVoices[e.target.value][0].name); // Set default voice for selected language
97
+ }}
98
+ className="w-full p-2 border rounded"
99
+ >
100
+ {Object.keys(languageVoices).map((lang) => (
101
+ <option key={lang} value={lang}>
102
+ {lang}
103
+ </option>
104
+ ))}
105
+ </select>
106
+ </div>
107
+
108
+ <div className="mb-4">
109
+ <label className="block text-gray-700 font-bold mb-2">Voice</label>
110
+ <select
111
+ value={name}
112
+ onChange={(e) => setName(e.target.value)}
113
+ className="w-full p-2 border rounded"
114
+ >
115
+ {languageVoices[languageCode].map((voice) => (
116
+ <option key={voice.name} value={voice.name}>
117
+ {voice.label}
118
+ </option>
119
+ ))}
120
+ </select>
121
+ </div>
122
+
123
+ <div className="flex justify-between mt-6">
124
+ <button
125
+ onClick={handleTextToSpeech} // Stop button handler
126
+ className="w-fit px-4 py-2 bg-blue-500 text-white rounded hover:shadow-lg hover:bg-blue-700 transition duration-200"
127
+ >
128
+ Generate
129
+ </button>
130
+
131
+ </div>
132
+
133
+ {audioUrl && (
134
+ <div className="mt-6">
135
+ <div className="flex items-center">
136
+ <audio controls src={audioUrl} className="w-full">
137
+ Your browser does not support the audio element.
138
+ </audio>
139
+ <button
140
+ onClick={handleDeleteAudio}
141
+ className="ml-4 px-4 py-2 bg-red-500 text-white rounded hover:bg-red-700 transition duration-200"
142
+ >
143
+ Delete
144
+ </button>
145
+ </div>
146
+ </div>
147
+ )}
148
+ </div>
149
+ </div>
150
+ );
151
+ }
152
+
153
+ export default TextToSpeech;
src/data/languageVoices.jsx ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const languageVoices = {
2
+ "en-US": [
3
+ { name: "en-US-Standard-A", label: "Alex" },
4
+ { name: "en-US-Standard-B", label: "Bob" },
5
+ { name: "en-US-Standard-C", label: "Charlie" },
6
+ { name: "en-US-Standard-D", label: "Dave" },
7
+ ],
8
+ "en-GB": [
9
+ { name: "en-GB-Standard-A", label: "David" },
10
+ { name: "en-GB-Standard-B", label: "Emma" },
11
+ { name: "en-GB-Standard-C", label: "Geraint" },
12
+ { name: "en-GB-Standard-D", label: "Brian" },
13
+ ],
14
+ "id-ID": [
15
+ { name: "id-ID-Standard-A", label: "Indra" },
16
+ { name: "id-ID-Standard-B", label: "Kartika" },
17
+ { name: "id-ID-Standard-C", label: "Kusuma" },
18
+ { name: "id-ID-Standard-D", label: "Nadia" },
19
+
20
+ ],
21
+ // Add more languages and voices as needed
22
+ };
23
+
24
+ export default languageVoices;
25
+
src/index.css ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import 'tailwindcss/base';
2
+ @import 'tailwindcss/components';
3
+ @import 'tailwindcss/utilities';
4
+
5
+ :root {
6
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
7
+ line-height: 1.5;
8
+ font-weight: 400;
9
+
10
+ color-scheme: light dark;
11
+ color: rgba(255, 255, 255, 0.87);
12
+ background-color: #292727;
13
+
14
+ font-synthesis: none;
15
+ text-rendering: optimizeLegibility;
16
+ -webkit-font-smoothing: antialiased;
17
+ -moz-osx-font-smoothing: grayscale;
18
+ }
19
+ body, html, #root, .App {
20
+ margin: 0;
21
+ padding: 0;
22
+ width: 100%;
23
+ height: 100%;
24
+ }
25
+
26
+ .App {
27
+ display: flex;
28
+ justify-content: center;
29
+ align-items: center;
30
+ min-height: 100vh;
31
+ }
32
+
33
+ a {
34
+ font-weight: 500;
35
+ color: #646cff;
36
+ text-decoration: inherit;
37
+ }
38
+ a:hover {
39
+ color: #535bf2;
40
+ }
41
+
42
+
43
+ h1 {
44
+ font-size: 3.2em;
45
+ line-height: 1.1;
46
+ }
47
+
48
+ button {
49
+ border-radius: 8px;
50
+ border: 1px solid transparent;
51
+ padding: 0.6em 1.2em;
52
+ font-size: 1em;
53
+ font-weight: 500;
54
+ font-family: inherit;
55
+ background-color: #1a1a1a;
56
+ cursor: pointer;
57
+ transition: border-color 0.25s;
58
+ }
59
+ button:hover {
60
+ border-color: #646cff;
61
+ }
62
+ button:focus,
63
+ button:focus-visible {
64
+ outline: 4px auto -webkit-focus-ring-color;
65
+ }
66
+
67
+ @media (prefers-color-scheme: light) {
68
+ :root {
69
+ color: #213547;
70
+ background-color: #ffffff;
71
+ }
72
+ a:hover {
73
+ color: #747bff;
74
+ }
75
+ button {
76
+ background-color: #f9f9f9;
77
+ }
78
+ }
79
+
80
+ .w-10 {
81
+ width: 2.5rem;
82
+ }
83
+
84
+ .h-10 {
85
+ height: 2.5rem;
86
+ }
87
+
88
+ .rounded-full {
89
+ border-radius: 9999px;
90
+ }
91
+
92
+ .object-cover {
93
+ object-fit: cover;
94
+ }
95
+
src/layouts/MainLayout.jsx ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import Sidebar from '../components/SideBarGPT';
3
+
4
+ const MainLayout = ({ children }) => {
5
+ return (
6
+ <div className="flex min-h-screen">
7
+ <Sidebar />
8
+ <div className="flex-1 p-6 bg-gray-100">
9
+ {children}
10
+ </div>
11
+ </div>
12
+ );
13
+ };
14
+
15
+ export default MainLayout;
src/main.jsx ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // src/main.jsx
2
+ import React from 'react';
3
+ import ReactDOM from 'react-dom/client';
4
+ import App from './App';
5
+ import './index.css';
6
+ import './chartSetup';
7
+
8
+ ReactDOM.createRoot(document.getElementById('root')).render(
9
+ <React.StrictMode>
10
+ <App />
11
+ </React.StrictMode>
12
+ );
src/pages/AnalyticsPage.jsx ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { Line, Bar, Doughnut } from 'react-chartjs-2';
3
+ import Sidebar from '../components/SideBarGPT';
4
+
5
+ const Analytics = () => {
6
+ // Sample data for charts
7
+ const messagesOverTimeData = {
8
+ labels: ['January', 'February', 'March', 'April', 'May', 'June'],
9
+ datasets: [
10
+ {
11
+ label: 'Messages',
12
+ data: [65, 59, 80, 81, 56, 55],
13
+ fill: false,
14
+ backgroundColor: 'rgba(75,192,192,0.2)',
15
+ borderColor: 'rgba(75,192,192,1)',
16
+ },
17
+ ],
18
+ };
19
+
20
+ const userBotMessagesData = {
21
+ labels: ['User', 'Bot'],
22
+ datasets: [
23
+ {
24
+ label: 'Messages',
25
+ data: [300, 450],
26
+ backgroundColor: ['#36A2EB', '#FF6384'],
27
+ },
28
+ ],
29
+ };
30
+
31
+ const responseTimeData = {
32
+ labels: ['<1s', '1-2s', '2-3s', '>3s'],
33
+ datasets: [
34
+ {
35
+ label: 'Response Time',
36
+ data: [50, 100, 75, 25],
37
+ backgroundColor: [
38
+ 'rgba(255, 99, 132, 0.2)',
39
+ 'rgba(54, 162, 235, 0.2)',
40
+ 'rgba(255, 206, 86, 0.2)',
41
+ 'rgba(75, 192, 192, 0.2)',
42
+ ],
43
+ borderColor: [
44
+ 'rgba(255, 99, 132, 1)',
45
+ 'rgba(54, 162, 235, 1)',
46
+ 'rgba(255, 206, 86, 1)',
47
+ 'rgba(75, 192, 192, 1)',
48
+ ],
49
+ borderWidth: 1,
50
+ },
51
+ ],
52
+ };
53
+
54
+ return (
55
+ <div className="flex">
56
+ <Sidebar />
57
+ <div className="ml-64 flex-1 p-6 bg-gray-100">
58
+ <div className="p-4 bg-white rounded-lg shadow">
59
+ <h2 className="text-2xl font-bold mb-4">Analytics</h2>
60
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
61
+ <div className="p-4 bg-gray-100 rounded-lg">
62
+ <h3 className="text-xl font-semibold mb-2">Messages Over Time</h3>
63
+ <Line data={messagesOverTimeData} />
64
+ </div>
65
+ <div className="p-4 bg-gray-100 rounded-lg">
66
+ <h3 className="text-xl font-semibold mb-2">User vs Bot Messages</h3>
67
+ <Doughnut data={userBotMessagesData} />
68
+ </div>
69
+ <div className="p-4 bg-gray-100 rounded-lg">
70
+ <h3 className="text-xl font-semibold mb-2">Response Time Distribution</h3>
71
+ <Bar data={responseTimeData} />
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ );
78
+ };
79
+
80
+ export default Analytics;
src/pages/ChatPage.jsx ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState } from 'react';
2
+ import ChatMessage from '../components/ChatMessage';
3
+ import Sidebar from '../components/SideBarGPT';
4
+
5
+ const Chat = () => {
6
+ const [messages, setMessages] = useState([]);
7
+ const [input, setInput] = useState('');
8
+
9
+ const handleSend = () => {
10
+ if (input.trim()) {
11
+ const newMessage = {
12
+ text: input,
13
+ timestamp: new Date().toLocaleTimeString(),
14
+ isUser: true,
15
+ };
16
+ setMessages([...messages, newMessage]);
17
+
18
+ // Simulate bot response
19
+ setTimeout(() => {
20
+ const botMessage = {
21
+ text: 'Onboarding clients is a critical process that sets the tone for your relationship and ensures that the client understands and is comfortable with your services. Here\'s a detailed procedure for onboarding clients, tailored to a technology or software development company:',
22
+ timestamp: new Date().toLocaleTimeString(),
23
+ isUser: false,
24
+ };
25
+ setMessages((prevMessages) => [...prevMessages, botMessage]);
26
+ }, 1000);
27
+
28
+ setInput('');
29
+ }
30
+ };
31
+
32
+ return (
33
+ <div className="flex">
34
+ <Sidebar />
35
+ <div className="ml-64 flex-1 p-6 bg-gray-100">
36
+ <div className="p-4 bg-white rounded-lg shadow">
37
+ <h2 className="text-2xl font-bold mb-4">Chat</h2>
38
+ <div className="flex flex-col h-96 bg-gray-100 rounded-lg overflow-hidden">
39
+ <div className="flex-1 p-4 overflow-y-auto">
40
+ {messages.map((message, index) => (
41
+ <ChatMessage key={index} message={message} isUser={message.isUser} />
42
+ ))}
43
+ </div>
44
+ <div className="flex p-4 border-t">
45
+ <input
46
+ type="text"
47
+ className="flex-1 p-2 border rounded-lg"
48
+ value={input}
49
+ onChange={(e) => setInput(e.target.value)}
50
+ placeholder="Type a message..."
51
+ />
52
+ <button
53
+ onClick={handleSend}
54
+ className="ml-4 px-4 py-2 bg-blue-600 text-white rounded-lg"
55
+ >
56
+ Send
57
+ </button>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ );
64
+ };
65
+
66
+ export default Chat;
src/pages/DocumentManagement.jsx ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import Sidebar from '../components/SideBarGPT';
3
+
4
+ const DocumentManagement = () => {
5
+ return (
6
+ <div className="flex">
7
+ <Sidebar />
8
+ <div className="ml-64 flex-1 p-6 bg-gray-100">
9
+ <div className="p-4 bg-white rounded-lg shadow">
10
+ <h2 className="text-2xl font-bold mb-4">Selected MDL List</h2>
11
+ <div className="space-y-4">
12
+ <div className="p-4 bg-blue-50 rounded-lg">
13
+ <h3 className="font-semibold">Project Details</h3>
14
+ </div>
15
+ <div className="p-4 bg-blue-50 rounded-lg">
16
+ <h3 className="font-semibold">SO Details</h3>
17
+ </div>
18
+ <div className="p-4 bg-blue-50 rounded-lg">
19
+ <h3 className="font-semibold">Master Document List</h3>
20
+ <table className="min-w-full bg-white rounded-lg">
21
+ <thead className="bg-gray-200">
22
+ <tr>
23
+ <th className="py-2 px-4">Document Title</th>
24
+ <th className="py-2 px-4">Planned Date</th>
25
+ <th className="py-2 px-4">Doc. No</th>
26
+ <th className="py-2 px-4">Latest Rev No</th>
27
+ <th className="py-2 px-4">Submission Dt</th>
28
+ <th className="py-2 px-4">Commented Dt</th>
29
+ <th className="py-2 px-4">Approved Dt</th>
30
+ <th className="py-2 px-4">Approval Status</th>
31
+ <th className="py-2 px-4">Options For Enquiry</th>
32
+ </tr>
33
+ </thead>
34
+ <tbody>
35
+ <tr>
36
+ <td className="border px-4 py-2">Strainer Drawing</td>
37
+ <td className="border px-4 py-2">06/17/2017</td>
38
+ <td className="border px-4 py-2">15201</td>
39
+ <td className="border px-4 py-2">R1</td>
40
+ <td className="border px-4 py-2">05/07/2017</td>
41
+ <td className="border px-4 py-2">05/07/2017</td>
42
+ <td className="border px-4 py-2">05/07/2017</td>
43
+ <td className="border px-4 py-2">APPROVED</td>
44
+ <td className="border px-4 py-2">
45
+ <button className="bg-blue-500 text-white px-2 py-1 rounded">Options</button>
46
+ </td>
47
+ </tr>
48
+ <tr>
49
+ <td className="border px-4 py-2">Strainer QCP</td>
50
+ <td className="border px-4 py-2">08/20/2017</td>
51
+ <td className="border px-4 py-2">EC5024</td>
52
+ <td className="border px-4 py-2">R4</td>
53
+ <td className="border px-4 py-2">05/07/2017</td>
54
+ <td className="border px-4 py-2">05/07/2017</td>
55
+ <td className="border px-4 py-2">05/07/2017</td>
56
+ <td className="border px-4 py-2">APPROVED</td>
57
+ <td className="border px-4 py-2">
58
+ <button className="bg-blue-500 text-white px-2 py-1 rounded">Options</button>
59
+ </td>
60
+ </tr>
61
+ <tr>
62
+ <td className="border px-4 py-2">Motor GA Drawing</td>
63
+ <td className="border px-4 py-2">08/30/2017</td>
64
+ <td className="border px-4 py-2">EC4121</td>
65
+ <td className="border px-4 py-2">R2</td>
66
+ <td className="border px-4 py-2">05/07/2017</td>
67
+ <td className="border px-4 py-2">05/07/2017</td>
68
+ <td className="border px-4 py-2">05/07/2017</td>
69
+ <td className="border px-4 py-2">APPROVED</td>
70
+ <td className="border px-4 py-2">
71
+ <button className="bg-blue-500 text-white px-2 py-1 rounded">Options</button>
72
+ </td>
73
+ </tr>
74
+ </tbody>
75
+ </table>
76
+ </div>
77
+ <div className="p-4 bg-blue-50 rounded-lg">
78
+ <h3 className="font-semibold">Revision History: Strainer Drawing</h3>
79
+ <table className="min-w-full bg-white rounded-lg">
80
+ <thead className="bg-gray-200">
81
+ <tr>
82
+ <th className="py-2 px-4">SR. No</th>
83
+ <th className="py-2 px-4">Document Title</th>
84
+ <th className="py-2 px-4">Doc. No</th>
85
+ <th className="py-2 px-4">Latest Rev No</th>
86
+ <th className="py-2 px-4">Submission Dt</th>
87
+ <th className="py-2 px-4">Commented Dt</th>
88
+ <th className="py-2 px-4">Approved Dt</th>
89
+ <th className="py-2 px-4">Approval Status</th>
90
+ <th className="py-2 px-4">Options For Enquiry</th>
91
+ </tr>
92
+ </thead>
93
+ <tbody>
94
+ <tr>
95
+ <td className="border px-4 py-2">1</td>
96
+ <td className="border px-4 py-2">Strainer Drawing</td>
97
+ <td className="border px-4 py-2">15201</td>
98
+ <td className="border px-4 py-2">R0</td>
99
+ <td className="border px-4 py-2">02/07/2017</td>
100
+ <td className="border px-4 py-2">02/07/2017</td>
101
+ <td className="border px-4 py-2">02/07/2017</td>
102
+ <td className="border px-4 py-2">Enquiry</td>
103
+ <td className="border px-4 py-2">
104
+ <button className="bg-blue-500 text-white px-2 py-1 rounded">Options</button>
105
+ </td>
106
+ </tr>
107
+ </tbody>
108
+ </table>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ </div>
114
+ );
115
+ };
116
+
117
+ export default DocumentManagement;
src/pages/ERPCredentialPage.jsx ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import ERPCredential from '../components/ERPCredentials';
2
+
3
+ function ERPCredentialPage() {
4
+ return <ERPCredential />;
5
+ }
6
+
7
+ export default ERPCredentialPage;
src/pages/Home.jsx ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import HomeDashboard from '../components/HomeDashboard';
2
+
3
+ function Home() {
4
+ return <HomeDashboard />;
5
+ }
6
+
7
+ export default Home;
src/pages/LoginPage.jsx ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import Login from '../components/Login';
2
+
3
+ function LoginPage() {
4
+ return <Login />;
5
+ }
6
+
7
+ export default LoginPage;
src/pages/OCRDashboardPage.jsx ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import Dashboard from '../components/OCRDashboard';
3
+
4
+ function DashboardPage () {
5
+ return (
6
+
7
+ <Dashboard />
8
+
9
+ );
10
+ }
11
+
12
+ export default DashboardPage;
src/pages/OCRTemplatePage.jsx ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import OCRTemplate from "../components/OCRTemplate";
2
+
3
+ function OCRTemplatePage() {
4
+ return <OCRTemplate />;
5
+ }
6
+
7
+ export default OCRTemplatePage;
src/pages/TextToSpeechPage.jsx ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import TextToSpeech from '../components/TextToSpeech';
2
+
3
+ function TextToSpeechPage() {
4
+ return <TextToSpeech />;
5
+ }
6
+
7
+ export default TextToSpeechPage;
src/services/api.js ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import axios from 'axios';
2
+ import axiosInstance from './axiosInstance';
3
+
4
+ // Ensure you have VITE_API_URL set in your .env file
5
+ const API_URL = import.meta.env.VITE_API_URL;
6
+
7
+ export const register = async (first_name, surname, email, phone, country, address, password) => {
8
+ const data = new URLSearchParams();
9
+ data.append('first_name', first_name);
10
+ data.append('surname', surname);
11
+ data.append('email', email);
12
+ data.append('phone', phone);
13
+ data.append('country', country);
14
+ data.append('address', address);
15
+ data.append('password', password);
16
+
17
+
18
+
19
+ try {
20
+ console.log('data', data);
21
+ const response = await axios.post(`${API_URL}/api/v1/user/`, data,{
22
+ headers: {
23
+ 'Content-Type': 'application/x-www-form-urlencoded',
24
+ 'accept': 'application/json',
25
+ },
26
+ });
27
+ return response.data;
28
+ } catch (error) {
29
+ console.error('Registration failed:', error);
30
+ throw error;
31
+ }
32
+ };
33
+
34
+ export const login = async (email, password) => {
35
+ const data = new URLSearchParams();
36
+ data.append('username', email);
37
+ data.append('password', password);
38
+
39
+ try {
40
+ const response = await axios.post(`${API_URL}/token`, data,{
41
+ headers: {
42
+ 'Content-Type': 'application/x-www-form-urlencoded',
43
+ 'accept': 'application/json',
44
+ },
45
+ });
46
+ return response;
47
+ } catch (error) {
48
+ console.error('Login failed:', error);
49
+ throw error;
50
+ }
51
+ };
52
+
53
+ export const logoutUser = () => {
54
+ localStorage.removeItem('token');
55
+ };
56
+
57
+ export const getTemplates = async (templateName) => {
58
+ try {
59
+ const response = await axiosInstance.get(`${API_URL}/api/v1/ocrtemplate/`, { params: { template_name: templateName } });
60
+ return response.data;
61
+ } catch (error) {
62
+ console.error('Error fetching templates:', error);
63
+ throw error;
64
+ }
65
+ };
66
+ export const createTemplate = async (templateName, fields, userId) => {
67
+ const data = {
68
+ template_name: templateName,
69
+ fields: fields,
70
+ user_id: userId,
71
+ };
72
+ try {
73
+ const response = await axiosInstance.post(`${API_URL}/api/v1/ocrtemplate/`, data);
74
+ return response.data;
75
+ } catch (error) {
76
+ console.error('Error creating template:', error);
77
+ throw error;
78
+ }
79
+ };
80
+ export const createOrUpdateTemplate = async (templateName, fields, userId, updated) => {
81
+ const data = {
82
+ template_name: templateName,
83
+ fields: fields,
84
+ user_id: userId,
85
+ };
86
+
87
+ try {
88
+ let response;
89
+ console.log(updated)
90
+ if (updated) {
91
+ // Update existing template
92
+ response = await axiosInstance.put(`${API_URL}/api/v1/ocrtemplate/templates/`, data);
93
+ } else {
94
+ // Create new template
95
+ response = await axiosInstance.post(`${API_URL}/api/v1/ocrtemplate/`, data);
96
+ }
97
+ return response.data;
98
+ } catch (error) {
99
+ console.error('Error creating/updating template:', error);
100
+ throw error;
101
+ }
102
+ };
103
+
104
+ export const deleteTemplate = async (templateName) => {
105
+ try {
106
+ const response = await axiosInstance.delete(`${API_URL}/api/v1/ocrtemplate/${templateName}`);
107
+ return response.data;
108
+ } catch (error) {
109
+ console.error('Error deleting template:', error);
110
+ throw error;
111
+ }
112
+ };
113
+ export const ocrProcess = async (formData) => {
114
+ try {
115
+ for (let [key, value] of formData.entries()) {
116
+ console.log(`${key}: ${value.name || value}`);
117
+ }
118
+
119
+ const response = await axiosInstance.post(`${API_URL}/api/v1/ocr/process`, formData);
120
+
121
+ // Check for HTTP errors
122
+ if (response.status !== 200) {
123
+ throw new Error(`Error: ${response.statusText}`);
124
+ }
125
+
126
+ const data = response.data; // axios automatically parses JSON
127
+ console.log("Success:", data);
128
+ return data; // Return the parsed data
129
+ } catch (error) {
130
+ console.error("Error:", error);
131
+ alert("There was an error processing the files.");
132
+ throw error; // Rethrow the error for further handling if needed
133
+ }
134
+ };
135
+
136
+
137
+ export const textToSpeech = async (text, languageCode, ssmlGender, name, pitch, speakingRate, volumeGainDb) => {
138
+ const data = {
139
+ text,
140
+ language_code: languageCode,
141
+ ssml_gender: ssmlGender,
142
+ name,
143
+ pitch,
144
+ speaking_rate: speakingRate,
145
+ volume_gain_db: volumeGainDb
146
+ };
147
+ // Get the token from your storage solution (e.g., localStorage)
148
+ const token = localStorage.getItem('token');
149
+ const headers = {
150
+ 'xi-api-key': 'u2', // Replace with the actual API key for the user
151
+ 'Content-Type': 'application/json',
152
+ 'Authorization': `Bearer ${token}`,
153
+ };
154
+
155
+ try {
156
+ console.log(data)
157
+ // const response = await axios.post(`${API_URL}/api/v1/text-to-speech/`, data, {headers, responseType: 'blob'});
158
+ const response = await axios.post(`${API_URL}/api/v1/text-to-speech/generate`, data, {headers});
159
+
160
+
161
+ // Create a URL for the blob and return it
162
+ // const audioUrl = window.URL.createObjectURL(new Blob([response.data]));
163
+
164
+ const audioUrl = response.data.data.key;
165
+ console.log(audioUrl )
166
+
167
+ return audioUrl
168
+ } catch (error) {
169
+ if (error.response) {
170
+ // The request was made and the server responded with a status code
171
+ // that falls out of the range of 2xx
172
+ console.error('Error response data:', error.response.data);
173
+ console.error('Error response status:', error.response.status);
174
+ console.error('Error response headers:', error.response.headers);
175
+ } else if (error.request) {
176
+ // The request was made but no response was received
177
+ console.error('Error request data:', error.request);
178
+ } else {
179
+ // Something happened in setting up the request that triggered an Error
180
+ console.error('Error message:', error.message);
181
+ }
182
+ console.error('Error config:', error.config);
183
+ throw error;
184
+ }
185
+ };
src/services/axiosInstance.js ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import axios from 'axios';
2
+
3
+ const API_URL = import.meta.env.VITE_API_URL;;
4
+
5
+ // Create an axios instance
6
+ const axiosInstance = axios.create({
7
+ baseURL: API_URL,
8
+ });
9
+
10
+ // Add a request interceptor
11
+ axiosInstance.interceptors.request.use(
12
+ (config) => {
13
+ // Get the token from your storage solution (e.g., localStorage)
14
+ const token = localStorage.getItem('token');
15
+ if (token) {
16
+ config.headers['Authorization'] = `Bearer ${token}`;
17
+ }
18
+ // Add any other custom headers here
19
+ config.headers['xi-api-key'] = 'u2';
20
+
21
+ // Set the appropriate Content-Type based on the request data type
22
+ if (config.data instanceof FormData) {
23
+ config.headers['Content-Type'] = 'multipart/form-data';
24
+ } else if (typeof config.data === 'object') {
25
+ config.headers['Content-Type'] = 'application/json';
26
+ }
27
+ return config;
28
+ },
29
+ (error) => {
30
+ // Handle the error
31
+ return Promise.reject(error);
32
+ }
33
+ );
34
+
35
+ // You can also add a response interceptor if you need to handle responses globally
36
+ axiosInstance.interceptors.response.use(
37
+ (response) => response,
38
+ (error) => {
39
+ // Handle the error
40
+ return Promise.reject(error);
41
+ }
42
+ );
43
+
44
+ export default axiosInstance;