From 2454b7cc6e21bf8c796ac3c820cc30d36354c5cf Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 21 Oct 2025 09:21:32 -0400 Subject: [PATCH 1/3] fix login bug with auth context --- frontend/src/App.tsx | 70 ++++++++++++---------- frontend/src/components/ProtectedRoute.tsx | 16 +++++ frontend/src/contexts/AuthContext.tsx | 36 +++++++++++ frontend/src/views/Login/Login.tsx | 16 +++-- 4 files changed, 102 insertions(+), 36 deletions(-) create mode 100644 frontend/src/components/ProtectedRoute.tsx create mode 100644 frontend/src/contexts/AuthContext.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index afe7688..21e5752 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -6,6 +6,8 @@ import { BrowserRouter as Router, Link, Route, Routes } from 'react-router-dom'; import './App.css'; import DoctorOrders from './views/DoctorOrders/DoctorOrders'; import Login from './views/Login/Login'; +import ProtectedRoute from './components/ProtectedRoute'; +import { AuthProvider } from './contexts/AuthContext'; import axios from 'axios'; axios.defaults.baseURL = process.env.REACT_APP_PIMS_BACKEND_URL @@ -17,37 +19,45 @@ const basename = process.env.REACT_APP_VITE_BASE?.replace(/\/$/, '') || ''; function App() { return ( - - -
- -
-
- -

Pharmacy

+ + + +
+ +
+
+ +

Pharmacy

+
+
+ + + + + + +
-
- - - - - - -
-
- -
- - {/* Initial load to login page, will need to change to check for user authentication to load to correct page */} - } /> - }> - }> - - - + +
+ + } /> + } /> + + + + } + /> + + + + ); } -export default App; +export default App; \ No newline at end of file diff --git a/frontend/src/components/ProtectedRoute.tsx b/frontend/src/components/ProtectedRoute.tsx new file mode 100644 index 0000000..d0bf3a8 --- /dev/null +++ b/frontend/src/components/ProtectedRoute.tsx @@ -0,0 +1,16 @@ +import { Navigate } from 'react-router-dom'; +import { useAuth } from '../contexts/AuthContext'; + +interface ProtectedRouteProps { + children: React.ReactNode; +} + +export default function ProtectedRoute({ children }: ProtectedRouteProps) { + const { isAuthenticated } = useAuth(); + + if (!isAuthenticated) { + return ; + } + + return <>{children}; +} \ No newline at end of file diff --git a/frontend/src/contexts/AuthContext.tsx b/frontend/src/contexts/AuthContext.tsx new file mode 100644 index 0000000..ec27d18 --- /dev/null +++ b/frontend/src/contexts/AuthContext.tsx @@ -0,0 +1,36 @@ +import React, { createContext, useContext, useState } from 'react'; + +interface AuthContextType { + token: string | null; + login: (token: string) => void; + logout: () => void; + isAuthenticated: boolean; +} + +const AuthContext = createContext(undefined); + +export function AuthProvider({ children }: { children: React.ReactNode }) { + const [token, setToken] = useState(null); + + const login = (newToken: string) => { + setToken(newToken); + }; + + const logout = () => { + setToken(null); + }; + + return ( + + {children} + + ); +} + +export function useAuth() { + const context = useContext(AuthContext); + if (!context) { + throw new Error('useAuth must be used within AuthProvider'); + } + return context; +} \ No newline at end of file diff --git a/frontend/src/views/Login/Login.tsx b/frontend/src/views/Login/Login.tsx index e2335b3..fa8f69d 100644 --- a/frontend/src/views/Login/Login.tsx +++ b/frontend/src/views/Login/Login.tsx @@ -3,10 +3,14 @@ import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; import { Avatar, Box, Button, Container, CssBaseline, TextField, Typography } from '@mui/material'; import axios from 'axios'; import * as React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useAuth } from '../../contexts/AuthContext'; import config from '../../config.json'; export default function Login() { - const [token, setToken] = React.useState(null); + const { login, isAuthenticated } = useAuth(); + const navigate = useNavigate(); + const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); const data = new FormData(event.currentTarget); @@ -23,16 +27,16 @@ export default function Login() { withCredentials: true }) .then(result => { - // do something with the token const scope = result.data.scope.split(' ').includes(config.scopeId); if (scope) { - setToken(result.data.access_token); + login(result.data.access_token); + navigate('/DoctorOrders'); } else { console.error('Unauthorized User'); } }) .catch(err => { - if (err.response.status === 401) { + if (err.response?.status === 401) { console.error('Unknown user'); } else { console.error(err); @@ -52,7 +56,7 @@ export default function Login() { alignItems: 'center' }} > - {token ? ( + {isAuthenticated ? ( @@ -90,4 +94,4 @@ export default function Login() {
); -} +} \ No newline at end of file From ebc57ef428ebd7eab7bf3b75b99d8e1397bb966e Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 21 Oct 2025 09:38:09 -0400 Subject: [PATCH 2/3] update keycloak url --- frontend/src/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/config.json b/frontend/src/config.json index 6ce29d5..43a06ef 100644 --- a/frontend/src/config.json +++ b/frontend/src/config.json @@ -1,6 +1,6 @@ { "realm": "ClientFhirServer", "client": "pims-login", - "auth": "http://localhost:8180/auth", + "auth": "http://localhost:8180", "scopeId": "pims" } From 7001b3b3aa6924bedd8804c941e6f7358c82b8e8 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 21 Oct 2025 09:59:28 -0400 Subject: [PATCH 3/3] run prettier/lint --- frontend/src/App.tsx | 2 +- frontend/src/components/ProtectedRoute.tsx | 2 +- frontend/src/contexts/AuthContext.tsx | 2 +- frontend/src/views/Login/Login.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 21e5752..3ee0b3d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -60,4 +60,4 @@ function App() { ); } -export default App; \ No newline at end of file +export default App; diff --git a/frontend/src/components/ProtectedRoute.tsx b/frontend/src/components/ProtectedRoute.tsx index d0bf3a8..6c467ed 100644 --- a/frontend/src/components/ProtectedRoute.tsx +++ b/frontend/src/components/ProtectedRoute.tsx @@ -13,4 +13,4 @@ export default function ProtectedRoute({ children }: ProtectedRouteProps) { } return <>{children}; -} \ No newline at end of file +} diff --git a/frontend/src/contexts/AuthContext.tsx b/frontend/src/contexts/AuthContext.tsx index ec27d18..cb06d2a 100644 --- a/frontend/src/contexts/AuthContext.tsx +++ b/frontend/src/contexts/AuthContext.tsx @@ -33,4 +33,4 @@ export function useAuth() { throw new Error('useAuth must be used within AuthProvider'); } return context; -} \ No newline at end of file +} diff --git a/frontend/src/views/Login/Login.tsx b/frontend/src/views/Login/Login.tsx index fa8f69d..8f024cc 100644 --- a/frontend/src/views/Login/Login.tsx +++ b/frontend/src/views/Login/Login.tsx @@ -94,4 +94,4 @@ export default function Login() { ); -} \ No newline at end of file +}