diff --git a/client-side/.env b/client-side/.env
index 4655bc2cf..e15d05f74 100644
--- a/client-side/.env
+++ b/client-side/.env
@@ -1,3 +1,4 @@
REACT_APP_BASE_URL='http://localhost:3000'
REACT_APP_SECRET_CODE_CAPVAL='6Ld5uBoqAAAAAKwPXqo5eanm9ZFSuOoBBSdl00pE'
REACT_APP_SERVER_URL='http://localhost:5000'
+REACT_APP_GOOGLE_CLIENT_ID='1074410346984-b9bsnokpb84s4afiim9t9d797k6orsvk.apps.googleusercontent.com'
diff --git a/client-side/package-lock.json b/client-side/package-lock.json
index e9beb0448..57a7885e1 100644
--- a/client-side/package-lock.json
+++ b/client-side/package-lock.json
@@ -17,6 +17,7 @@
"@mui/x-charts": "^7.10.0",
"@mui/x-data-grid": "^7.9.0",
"@mui/x-date-pickers": "^7.12.0",
+ "@react-oauth/google": "^0.12.1",
"@reduxjs/toolkit": "^2.2.6",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
@@ -25,6 +26,7 @@
"axios": "^1.7.2",
"dayjs": "^1.11.12",
"formik": "^2.4.6",
+ "gapi-script": "^1.2.0",
"html2canvas": "^1.4.1",
"html2pdf.js": "^0.10.2",
"jest": "^29.7.0",
@@ -5706,6 +5708,16 @@
}
}
},
+ "node_modules/@react-oauth/google": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/@react-oauth/google/-/google-0.12.1.tgz",
+ "integrity": "sha512-qagsy22t+7UdkYAiT5ZhfM4StXi9PPNvw0zuwNmabrWyMKddczMtBIOARflbaIj+wHiQjnMAsZmzsUYuXeyoSg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
"node_modules/@react-spring/animated": {
"version": "9.7.4",
"resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.4.tgz",
@@ -15687,6 +15699,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/gapi-script": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gapi-script/-/gapi-script-1.2.0.tgz",
+ "integrity": "sha512-NKTVKiIwFdkO1j1EzcrWu/Pz7gsl1GmBmgh+qhuV2Ytls04W/Eg5aiBL91SCiBM9lU0PMu7p1hTVxhh1rPT5Lw==",
+ "license": "MIT"
+ },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
diff --git a/client-side/package.json b/client-side/package.json
index 491be4732..f0fe8029c 100644
--- a/client-side/package.json
+++ b/client-side/package.json
@@ -12,6 +12,7 @@
"@mui/x-charts": "^7.10.0",
"@mui/x-data-grid": "^7.9.0",
"@mui/x-date-pickers": "^7.12.0",
+ "@react-oauth/google": "^0.12.1",
"@reduxjs/toolkit": "^2.2.6",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
@@ -20,6 +21,7 @@
"axios": "^1.7.2",
"dayjs": "^1.11.12",
"formik": "^2.4.6",
+ "gapi-script": "^1.2.0",
"html2canvas": "^1.4.1",
"html2pdf.js": "^0.10.2",
"jest": "^29.7.0",
diff --git a/client-side/src/App.jsx b/client-side/src/App.jsx
index dedb45f2f..0aaef8c3b 100644
--- a/client-side/src/App.jsx
+++ b/client-side/src/App.jsx
@@ -6,18 +6,22 @@ import { router } from './router/router.jsx';
import { store } from './redux/store.jsx';
import { SnackbarProvider } from 'notistack';
import './App.scss';
+import { GoogleOAuthProvider } from '@react-oauth/google';
+
+const clientId = process.env.REACT_APP_GOOGLE_CLIENT_ID;
function App() {
- return (
- <>
+ return (
+
-
-
-
+
+
+
-
- >
+
+
);
}
+
export default App;
diff --git a/client-side/src/axios/axiosInstance.js b/client-side/src/axios/axiosInstance.js
new file mode 100644
index 000000000..bc4ff5b6d
--- /dev/null
+++ b/client-side/src/axios/axiosInstance.js
@@ -0,0 +1,32 @@
+import axios from 'axios';
+
+const axiosInstance = axios.create({
+ baseURL: process.env.REACT_APP_SERVER_URL,
+});
+
+axiosInstance.interceptors.request.use(
+ (config) => {
+ const token = localStorage.getItem('authToken');
+ if (token) {
+ config.headers['Authorization'] = `Bearer ${token}`;
+ }
+ return config;
+ },
+ (error) => {
+ return Promise.reject(error);
+ }
+);
+
+axiosInstance.interceptors.response.use(
+ (response) => {
+ return response;
+ },
+ (error) => {
+ if (error.response.status === 401) {
+ window.location.href = '/login';
+ }
+ return Promise.reject(error);
+ }
+);
+
+export default axiosInstance;
diff --git a/client-side/src/axios/middleware.js b/client-side/src/axios/middleware.js
index 62503f44b..4479526a1 100644
--- a/client-side/src/axios/middleware.js
+++ b/client-side/src/axios/middleware.js
@@ -1,27 +1,21 @@
-import axios from 'axios';
+import axiosInstance from './axiosInstance';
-const url = process.env.REACT_APP_SERVER_URL;
-
-export async function handleGet(path) {
- const response = await axios.create({ baseURL: url }).get(path);
+export async function handleGet(path, config = {}) {
+ const response = await axiosInstance.get(path, config);
return response;
-
};
-export async function handlePost(path, data) {
- const response = await axios.create({ baseURL: url }).post(path, data);
+export async function handlePost(path, data, config = {}) {
+ const response = await axiosInstance.post(path, data, config);
return response;
-
};
-export async function handlePut(path, data) {
- const response = await axios.create({ baseURL: url }).put(path, data);
+export async function handlePut(path, data, config = {}) {
+ const response = await axiosInstance.put(path, data, config);
return response;
-
};
-export async function handleDelete(path) {
- const response = await axios.create({ baseURL: url }).delete(path);
+export async function handleDelete(path, config = {}) {
+ const response = await axiosInstance.delete(path, config);
return response;
-
};
diff --git a/client-side/src/components/Report/googleDriveUploader.jsx b/client-side/src/components/Report/googleDriveUploader.jsx
new file mode 100644
index 000000000..4306e76d4
--- /dev/null
+++ b/client-side/src/components/Report/googleDriveUploader.jsx
@@ -0,0 +1,57 @@
+import React, { useEffect } from 'react';
+import { gapi } from 'gapi-script';
+import GenericButton from '../../stories/Button/GenericButton';
+import { GOOGLE_API, MESSAGES, BUTTON_LABELS } from '../../constants/googleDriveConstants';
+
+const GoogleDriveUploader = () => {
+ const CLIENT_ID = process.env.REACT_APP_GOOGLE_CLIENT_ID;
+
+ useEffect(() => {
+ function start() {
+ gapi.client.init({
+ clientId: CLIENT_ID,
+ scope: GOOGLE_API.scopes,
+ }).then(() => {
+ console.log(MESSAGES.gapiClientInitialized);
+ }).catch(error => {
+ console.error(MESSAGES.gapiInitError, error);
+ });
+ }
+
+ gapi.load('client:auth2', start);
+ }, [CLIENT_ID]);
+
+ const handleAuthClick = async () => {
+ try {
+ await gapi.auth2.getAuthInstance().signIn({
+ prompt: GOOGLE_API.prompt,
+ });
+ console.log(MESSAGES.gapiSignInSuccess);
+ } catch (error) {
+ console.error(MESSAGES.signInError, error);
+ }
+ };
+
+ const handleSignoutClick = () => {
+ gapi.auth2.getAuthInstance().signOut();
+ };
+
+ return (
+
+
+
+
+ );
+};
+
+export default GoogleDriveUploader;
diff --git a/client-side/src/components/Report/managerGoogleDrive.jsx b/client-side/src/components/Report/managerGoogleDrive.jsx
new file mode 100644
index 000000000..ed42be550
--- /dev/null
+++ b/client-side/src/components/Report/managerGoogleDrive.jsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import GoogleDriveUploader from './googleDriveUploader';
+import UploadToGoogleDrive from './uploadToGoogleDrive';
+
+const ManagerGoogleDrive = () => {
+ const fileContent = "Hello, world!";
+ const fileName = 'yourfile.txt';
+ const fileMimeType = 'text/plain';
+
+ return (
+
+
+
+
+ );
+};
+
+export default ManagerGoogleDrive;
diff --git a/client-side/src/components/Report/uploadToGoogleDrive.jsx b/client-side/src/components/Report/uploadToGoogleDrive.jsx
new file mode 100644
index 000000000..7124ee1ca
--- /dev/null
+++ b/client-side/src/components/Report/uploadToGoogleDrive.jsx
@@ -0,0 +1,52 @@
+import { useGoogleLogin } from '@react-oauth/google';
+import GenericButton from '../../stories/Button/GenericButton';
+import { FILE_DETAILS, URLS, MESSAGES, BUTTON_LABELS } from '../../constants/googleDriveConstants';
+import { handlePost } from '../../axios/middleware';
+
+const UploadToGoogleDrive = () => {
+ const CLIENT_ID = process.env.REACT_APP_GOOGLE_CLIENT_ID;
+
+ const login = useGoogleLogin({
+ clientId: CLIENT_ID,
+ onSuccess: async (tokenResponse) => {
+ const accessToken = tokenResponse.access_token;
+
+ const fileData = new Blob([FILE_DETAILS.content], { type: FILE_DETAILS.mimeType });
+
+ const form = new FormData();
+ form.append('metadata', new Blob([JSON.stringify({ name: FILE_DETAILS.name, mimeType: FILE_DETAILS.mimeType })], { type: 'application/json' }));
+ form.append('file', fileData);
+
+ try {
+ const response = await handlePost(
+ URLS.uploadUrl,
+ form,
+ {
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ 'Content-Type': 'multipart/related',
+ },
+ }
+ );
+ console.log('File uploaded successfully:', response);
+ } catch (error) {
+ console.error(MESSAGES.uploadError, error);
+ }
+ },
+ onError: error => console.error(MESSAGES.loginFailed, error)
+ });
+
+ return (
+
+
+
+ );
+};
+
+export default UploadToGoogleDrive;
+
diff --git a/client-side/src/constants/googleDriveConstants.js b/client-side/src/constants/googleDriveConstants.js
new file mode 100644
index 000000000..ae34666fd
--- /dev/null
+++ b/client-side/src/constants/googleDriveConstants.js
@@ -0,0 +1,31 @@
+export const BUTTON_LABELS = {
+ upload: 'Upload to Google Drive',
+ signIn: 'Sign in with Google',
+ signOut: 'Sign out',
+};
+
+export const FILE_DETAILS = {
+ name: 'yourfile.txt',
+ mimeType: 'text/plain',
+ content: 'Hello, world!',
+};
+
+export const URLS = {
+ uploadUrl: 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart',
+};
+
+export const MESSAGES = {
+ loginFailed: 'Login failed:',
+ uploadError: 'Error uploading file:',
+ signInError: 'Error signing in:',
+ signOutError: 'Error signing out:',
+ gapiInitError: 'Error initializing GAPI client:',
+ gapiSignInSuccess: 'Successfully signed in',
+ gapiClientInitialized: 'GAPI client initialized',
+};
+
+export const GOOGLE_API = {
+ clientId: '1074410346984-b9bsnokpb84s4afiim9t9d797k6orsvk.apps.googleusercontent.com',
+ scopes: 'https://www.googleapis.com/auth/drive.file',
+ prompt: 'select_account',
+};
diff --git a/client-side/src/router/router.jsx b/client-side/src/router/router.jsx
index 7bfa68907..dc8b57cd5 100644
--- a/client-side/src/router/router.jsx
+++ b/client-side/src/router/router.jsx
@@ -1,8 +1,8 @@
import React from "react";
import {createBrowserRouter } from "react-router-dom";
-import ProfileList from "../components/profileComponent.jsx";
import Layout from "./layout.jsx";
import Login from "../login/Login.jsx";
+import ManagerGoogleDrive from "../components/Report/managerGoogleDrive.jsx";
export const router = createBrowserRouter([
{
path: '',
@@ -16,13 +16,13 @@ export const router = createBrowserRouter([
path: '/home',
element: home
},
- {
- path: '/profiles',
- element:
- },
{
path: '/login',
element:
+ },
+ {
+ path: '/reports',
+ element:
}
]
},
diff --git a/server-side/controllers/preference.controller.js b/server-side/controllers/preference.controller.js
index 46f71ac85..1744df6f6 100644
--- a/server-side/controllers/preference.controller.js
+++ b/server-side/controllers/preference.controller.js
@@ -64,10 +64,6 @@ export const deletePreference = async (req, res, next) => {
res.json({ message: 'deleted succesfully!!' }).status(204)
} catch (error) {
-<<<<<<< HEAD
- return next({ message: error.message });
-=======
return next({ message: error.message, status: 500 });
->>>>>>> 9b418204928598b6d7eda4b6b9ba01463f7803d9
}
};
diff --git a/server-side/router/preference.router.js b/server-side/router/preference.router.js
index e0f8baff4..114a4a803 100644
--- a/server-side/router/preference.router.js
+++ b/server-side/router/preference.router.js
@@ -2,15 +2,6 @@ import express from 'express';
import upload from '../middleware/uploadFiles.js';
import {getAllPreference,getPreferenceById,updatePreference,deletePreference,addPreference} from '../controllers/preference.controller.js'
-<<<<<<< HEAD
-const router=express.Router();
-router.get('/preferences',getAllPreference);
-router.get('/preferences/:id',getPreferenceById);
-router.post('/preferences',upload.single('soundVoice'),addPreference);
-router.put('/preferences/:id',upload.single('soundVoice'),updatePreference);
-router.delete('/preferences/:id',deletePreference);
-export default router;
-=======
const preferencesRouter=express.Router();
preferencesRouter.get('/',getAllPreference);
@@ -20,4 +11,3 @@ preferencesRouter.put('/:id',upload.single('soundVoice'),updatePreference);
preferencesRouter.delete('/:id',deletePreference);
export default preferencesRouter;
->>>>>>> 9b418204928598b6d7eda4b6b9ba01463f7803d9