diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts new file mode 100644 index 0000000..4f11a03 --- /dev/null +++ b/frontend/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b7430c6..62baa47 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,7 @@ "name": "vite-react-typescript-starter", "version": "0.0.0", "dependencies": { + "@auth0/auth0-react": "^2.3.0", "@mediapipe/camera_utils": "^0.3.1675466862", "@mediapipe/drawing_utils": "^0.3.1675466124", "@mediapipe/hands": "^0.4.1675469240", @@ -18,6 +19,7 @@ }, "devDependencies": { "@eslint/js": "^9.9.1", + "@types/node": "^22.13.14", "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", @@ -58,6 +60,23 @@ "node": ">=6.0.0" } }, + "node_modules/@auth0/auth0-react": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@auth0/auth0-react/-/auth0-react-2.3.0.tgz", + "integrity": "sha512-YYTc/DWWigKC9fURufR/79h3+3DAnIzbfEzJLZ8Z4Q0BXE0azru3pKUbU+vYzS4lMAJkclwLuAbUnLjK81vCpA==", + "dependencies": { + "@auth0/auth0-spa-js": "^2.1.3" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17 || ^18 || ^19", + "react-dom": "^16.11.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/@auth0/auth0-spa-js": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@auth0/auth0-spa-js/-/auth0-spa-js-2.1.3.tgz", + "integrity": "sha512-NMTBNuuG4g3rame1aCnNS5qFYIzsTUV5qTFPRfTyYFS1feS6jsCBR+eTq9YkxCp1yuoM2UIcjunPaoPl77U9xQ==" + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -1337,6 +1356,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/node": { + "version": "22.13.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", + "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "dev": true, + "dependencies": { + "undici-types": "~6.20.0" + } + }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -3738,6 +3766,12 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index c74c417..186ac29 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@auth0/auth0-react": "^2.3.0", "@mediapipe/camera_utils": "^0.3.1675466862", "@mediapipe/drawing_utils": "^0.3.1675466124", "@mediapipe/hands": "^0.4.1675469240", @@ -20,6 +21,7 @@ }, "devDependencies": { "@eslint/js": "^9.9.1", + "@types/node": "^22.13.14", "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ddca4a3..9fd0e58 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,12 +1,16 @@ -import React from 'react' -import Canvas from './components/Canvas' -import Toolbar from './components/Toolbar' -import Header from './components/Header' -import HandDrawing from './components/HandDrawing' -import { DrawingProvider } from './context/DrawingContext' -import { HandGestureProvider } from './context/HandGestureContext' +import React from 'react'; +import { useAuth0 } from '@auth0/auth0-react'; +import { withAuthenticationRequired } from '@auth0/auth0-react'; +import Canvas from './components/Canvas'; +import Toolbar from './components/Toolbar'; +import Header from './components/Header'; +import HandDrawing from './components/HandDrawing'; +import LoginButton from './components/LoginButton'; +import { DrawingProvider } from './context/DrawingContext'; +import { HandGestureProvider } from './context/HandGestureContext'; -function App() { +// Protected component that requires authentication +const ProtectedApp = () => { return ( @@ -21,7 +25,57 @@ function App() { - ) + ); +}; + +// Wrap the protected component with authentication +const ProtectedAppWithAuth = withAuthenticationRequired(ProtectedApp); + +function App() { + const { isAuthenticated } = useAuth0(); + + if (!isAuthenticated) { + return ( +
+
+ {/* Logo and Title */} +
+
+ C +
+

CoCo

+

Create, collaborate, and share your drawings

+
+ + {/* Login Button */} +
+ +
+ + {/* Feature Grid */} +
+
+
🎨
+

Draw Freely

+

Express your creativity with our intuitive drawing tools

+
+
+
🤝
+

Collaborate

+

Work together in real-time with others

+
+
+
+

Hand Gestures

+

Draw naturally with hand tracking support

+
+
+
+
+ ); + } + + return ; } -export default App +export default App; \ No newline at end of file diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index 7cb2758..3a20da4 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -1,9 +1,13 @@ import React, { useState } from 'react' import { useDrawing } from '../context/DrawingContext' import { Download, Share2, Clock, User, ChevronDown } from 'lucide-react' +import LoginButton from './LoginButton' +import LogoutButton from './LogoutButton' +import { useAuth0 } from "@auth0/auth0-react" const Header: React.FC = () => { const { state } = useDrawing() + const { isAuthenticated } = useAuth0() const [documentName, setDocumentName] = useState('Untitled') const handleExport = () => { @@ -92,6 +96,11 @@ const Header: React.FC = () => {
+ {isAuthenticated ? ( + + ) : ( + + )} diff --git a/frontend/src/components/LoginButton.tsx b/frontend/src/components/LoginButton.tsx new file mode 100644 index 0000000..7f61d3e --- /dev/null +++ b/frontend/src/components/LoginButton.tsx @@ -0,0 +1,17 @@ +import React from "react"; +import { useAuth0 } from "@auth0/auth0-react"; + +const LoginButton = () => { + const { loginWithRedirect } = useAuth0(); + + return ( + + ); +}; + +export default LoginButton; \ No newline at end of file diff --git a/frontend/src/components/LogoutButton.tsx b/frontend/src/components/LogoutButton.tsx new file mode 100644 index 0000000..d16b8d1 --- /dev/null +++ b/frontend/src/components/LogoutButton.tsx @@ -0,0 +1,13 @@ +import { useAuth0 } from "@auth0/auth0-react"; + +const LogoutButton = () => { + const { logout } = useAuth0(); + + return ( + + ); +}; + +export default LogoutButton; \ No newline at end of file diff --git a/frontend/src/loginPage.tsx b/frontend/src/loginPage.tsx new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 6f4ac9b..af69432 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -2,9 +2,22 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import App from './App.tsx' import './index.css' +import {Auth0Provider} from "@auth0/auth0-react" + +const domain = import.meta.env.VITE_AUTH0_DOMAIN; +const clientId = import.meta.env.VITE_AUTH0_CLIENT_ID; createRoot(document.getElementById('root')!).render( - + + + , ) +