Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Healthcare app: Add Login signup functionality #4

Merged
merged 13 commits into from
Feb 8, 2024
38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.7",
"js-cookie": "^3.0.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.0",
Expand Down
28 changes: 19 additions & 9 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import { Route, Routes } from 'react-router-dom';
import './App.css';
import Doctors from './pages/Doctors';
import Navbar from './components/navbar/Navbar';
import MyAppointments from './pages/MyAppointments';
import AddDoctor from './pages/AddDoctor';
import Doctors from './pages/Doctors';
import BookAppointment from './pages/BookAppointment';
import DeleteDoctor from './pages/DeleteDoctor';
import DoctorDetails from './pages/DoctorDetails';
import SplashScreen from './components/splashScreen/SplashScreen';
import Login from './components/login/login';
import Register from './components/register/Register';
import ProtectedRoute from './components/ProtectedRoute';
import Layout from './components/layout';

function App() {
return (
<div className="app">
<Navbar />
<Routes>
<Route path="/" element={<Doctors />} />
<Route path="/doctors/:id" element={<DoctorDetails />} />
<Route path="/book-appointment" element={<BookAppointment />} />
<Route path="/my-appointments" element={<MyAppointments />} />
<Route path="/add-doctor" element={<AddDoctor />} />
<Route path="/delete-doctor" element={<DeleteDoctor />} />
<Route exact path="/" element={<SplashScreen />} />
<Route exact path="/login" element={<Login />} />
<Route exact path="/signup" element={<Register />} />
<Route element={<ProtectedRoute />}>
<Route path="/doctors" element={<Layout />}>
<Route path="/doctors" element={<Doctors />} />
<Route path="/doctors/:id" element={<DoctorDetails />} />
<Route path="/doctors/book-appointment" element={<BookAppointment />} />
<Route path="/doctors/my-appointments" element={<MyAppointments />} />
<Route path="/doctors/add-doctor" element={<AddDoctor />} />
<Route path="/doctors/delete-doctor" element={<DeleteDoctor />} />
</Route>
</Route>
</Routes>
</div>
);
Expand Down
Binary file added src/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/components/ProtectedRoute.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import { Outlet, Navigate } from 'react-router-dom';
import Cookies from 'js-cookie';

const ProtectedRoute = () => {
const token = Cookies.get('jwt_token');
return token ? <Outlet /> : <Navigate to="/" replace />;
};

export default ProtectedRoute;
16 changes: 16 additions & 0 deletions src/components/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Outlet } from 'react-router-dom';
import Navbar from './navbar/Navbar';
import layout from './layout.module.css';

const Layout = () => (
<div className={layout.container}>
<div>
<Navbar />
</div>
<div>
<Outlet />
</div>
</div>
);

export default Layout;
3 changes: 3 additions & 0 deletions src/components/layout.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.container {
display: flex;
}
68 changes: 68 additions & 0 deletions src/components/login/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { NavLink, useNavigate } from 'react-router-dom';
import { loginAsync } from '../../redux/user/userSlice';
import login from './login.module.css';

const Login = () => {
const { loginError, success } = useSelector((store) => store.user);
const dispatch = useDispatch();
const navigate = useNavigate();
const formRef = useRef();

const handleSubmit = async (e) => {
e.preventDefault();

const formData = new FormData(formRef.current);
const email = formData.get('email');
const password = formData.get('password');

const data = {
user: { email, password },
};

try {
await dispatch(loginAsync(data));
navigate('/doctors');
e.target.reset();
} catch (error) {
throw new Error(error);
}
};

return (
<section className={login.container}>
<div>
<h2>Login</h2>
<form onSubmit={handleSubmit} ref={formRef}>
<input
type="email"
name="email"
id="email"
placeholder="Enter your email"
required
/>
<input
type="password"
name="password"
id="password"
placeholder="Enter your password"
required
/>
<div>
<button type="submit">
Log in
</button>
<NavLink to="/signup">
<button type="button">Sign Up</button>
</NavLink>
</div>
{loginError && <p>{loginError}</p>}
{success && <p>{success}</p>}
</form>
</div>
</section>
);
};

export default Login;
7 changes: 7 additions & 0 deletions src/components/login/login.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.container {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
75 changes: 56 additions & 19 deletions src/components/navbar/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,58 @@
import { NavLink } from 'react-router-dom';
import './navbar.css';
import { NavLink, useLocation, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import Cookies from 'js-cookie';
import { logout } from '../../redux/user/userSlice';
import logo from '../../assets/logo.png';
import navbar from './navbar.module.css';

const Navbar = () => (
<nav className="nav-container">
<div className="profile">
<p>Mayito Ismail</p>
</div>
<div className="nav-links">
<NavLink to="/">Doctors</NavLink>
<NavLink to="/book-appointment">Book Appointment</NavLink>
<NavLink to="/my-appointments">My Appointments</NavLink>
<NavLink to="/add-doctor">Add Doctor</NavLink>
<NavLink to="/delete-doctor">Delete Doctor</NavLink>
</div>
<button type="button" className="logout">
Log Out
</button>
</nav>
);
const Navbar = () => {
const { userData } = useSelector((store) => store.user);
const location = useLocation();

const dispatch = useDispatch();
const navigate = useNavigate();
const logoutUser = () => {
dispatch(logout());
Cookies.remove('jwt_token');
Cookies.remove('user_info');
navigate('/');
};
return (
<nav className={navbar.nav_container}>
<div className={navbar.profile}>
<img src={logo} alt="Logo" className={navbar.logo} />
<p>{`Welcome "${userData.user.name}"`}</p>
</div>
<div className={navbar.nav_links}>
<NavLink to="/doctors" className={location.pathname === '/doctors' ? navbar.active : ''}>Doctors</NavLink>
<NavLink to="/doctors/book-appointment" className={location.pathname === '/doctors/book-appointment' ? navbar.active : ''}>Book Appointment</NavLink>
<NavLink to="/doctors/my-appointments" className={location.pathname === '/doctors/my-appointments' ? navbar.active : ''}>My Appointments</NavLink>
<NavLink to="/doctors/add-doctor" className={location.pathname === '/doctors/add-doctor' ? navbar.active : ''}>Add Doctor</NavLink>
<NavLink to="/doctors/delete-doctor" className={location.pathname === '/doctors/delete-doctor' ? navbar.active : ''}>Delete Doctor</NavLink>
</div>
<button
className={navbar.logout}
onClick={logoutUser}
type="button"
>
Logout
</button>
<ul className={navbar.social_links}>
<li>
<img src="https://jade-rabanadas-479b96.netlify.app/static/media/fb.6ede2e0d2f244fec1b76327b30e2d180.svg" alt="" />
</li>
<li>
<img src="https://jade-rabanadas-479b96.netlify.app/static/media/x.068f9efee7b52e070424b4c2925f2960.svg" alt="" />
</li>
<li>
<img src="https://jade-rabanadas-479b96.netlify.app/static/media/google.cf737c214060d873db8410bbd35aa463.svg" alt="" />
</li>
<li>
<img src="https://jade-rabanadas-479b96.netlify.app/static/media/linkedin.6bfb62956b5c794df40ab6045a56d21d.svg" alt="" />
</li>
</ul>
<p className={navbar.copyright}>@2024 Health Care App</p>
</nav>
);
};
export default Navbar;
36 changes: 0 additions & 36 deletions src/components/navbar/navbar.css

This file was deleted.

Loading
Loading