├── yarn
├── .firebaserc
├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── manifest.json
└── index.html
├── src
├── images
│ ├── bg.png
│ ├── chair.png
│ ├── login.png
│ ├── cavity.png
│ ├── doctor.png
│ ├── dribbble_1.gif
│ ├── fluoride.png
│ ├── footer-bg.png
│ ├── people-1.png
│ ├── people-2.png
│ ├── people-3.png
│ ├── treatment.png
│ ├── whitening.png
│ ├── doctor-small.png
│ └── appointment-bg.png
├── Pages
│ ├── Dashboard
│ │ ├── AddDoctor
│ │ │ └── AddDoctor.js
│ │ ├── DashboardHome
│ │ │ └── DashboardHome.js
│ │ ├── MakeAdmin
│ │ │ └── MakeAdmin.js
│ │ ├── Appointments
│ │ │ └── Appointments.js
│ │ └── Dashboard
│ │ │ └── Dashboard.js
│ ├── Login
│ │ ├── Login
│ │ │ ├── Firebase
│ │ │ │ ├── firebase.config.js
│ │ │ │ └── firebase.init.js
│ │ │ └── Login.js
│ │ ├── PrivateRoute
│ │ │ └── PrivateRoute.js
│ │ ├── AdminRoute
│ │ │ └── AdminRoute.js
│ │ └── Register
│ │ │ └── Register.js
│ ├── Home
│ │ ├── Home
│ │ │ └── Home.js
│ │ ├── Service
│ │ │ └── Service.js
│ │ ├── Banner
│ │ │ └── Banner.js
│ │ ├── AppointmentBanner
│ │ │ └── AppointmentBanner.js
│ │ └── Services
│ │ │ └── Services.js
│ ├── Appointment
│ │ ├── Appointment
│ │ │ └── Appointment.js
│ │ ├── AppointmentHeader
│ │ │ └── AppointmentHeader.js
│ │ ├── Booking
│ │ │ └── Booking.js
│ │ ├── AvailableAppointments
│ │ │ └── AvailableAppointments.js
│ │ └── BookingModal
│ │ │ └── BookingModal.js
│ └── Shared
│ │ ├── Calendar
│ │ └── Calendar.js
│ │ └── Navigation
│ │ └── Navigation.js
├── hooks
│ ├── useAuth.js
│ └── useFirebase.js
├── setupTests.js
├── App.test.js
├── index.css
├── reportWebVitals.js
├── contexts
│ └── AuthProvider
│ │ └── AuthProvider.js
├── index.js
├── App.css
├── App.js
└── logo.svg
├── firebase.json
├── .gitignore
├── package.json
├── .firebase
└── hosting.YnVpbGQ.cache
└── README.md
/yarn:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "doctors-portal-dc289"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/images/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/bg.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/src/images/chair.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/chair.png
--------------------------------------------------------------------------------
/src/images/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/login.png
--------------------------------------------------------------------------------
/src/images/cavity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/cavity.png
--------------------------------------------------------------------------------
/src/images/doctor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/doctor.png
--------------------------------------------------------------------------------
/src/images/dribbble_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/dribbble_1.gif
--------------------------------------------------------------------------------
/src/images/fluoride.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/fluoride.png
--------------------------------------------------------------------------------
/src/images/footer-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/footer-bg.png
--------------------------------------------------------------------------------
/src/images/people-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/people-1.png
--------------------------------------------------------------------------------
/src/images/people-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/people-2.png
--------------------------------------------------------------------------------
/src/images/people-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/people-3.png
--------------------------------------------------------------------------------
/src/images/treatment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/treatment.png
--------------------------------------------------------------------------------
/src/images/whitening.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/whitening.png
--------------------------------------------------------------------------------
/src/images/doctor-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/doctor-small.png
--------------------------------------------------------------------------------
/src/images/appointment-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProgrammingHero1/batch4-doctors-portal-client-module-73-5/HEAD/src/images/appointment-bg.png
--------------------------------------------------------------------------------
/src/Pages/Dashboard/AddDoctor/AddDoctor.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const AddDoctor = () => {
4 | return (
5 |
6 |
Add A Doctor
7 |
8 | );
9 | };
10 |
11 | export default AddDoctor;
--------------------------------------------------------------------------------
/src/hooks/useAuth.js:
--------------------------------------------------------------------------------
1 | import { AuthContext } from "../contexts/AuthProvider/AuthProvider";
2 | import { useContext } from 'react';
3 |
4 | const useAuth = () => {
5 | const auth = useContext(AuthContext);
6 | return auth;
7 | }
8 |
9 | export default useAuth;
--------------------------------------------------------------------------------
/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render();
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "public": "build",
4 | "ignore": [
5 | "firebase.json",
6 | "**/.*",
7 | "**/node_modules/**"
8 | ],
9 | "rewrites": [
10 | {
11 | "source": "**",
12 | "destination": "/index.html"
13 | }
14 | ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/Pages/Login/Login/Firebase/firebase.config.js:
--------------------------------------------------------------------------------
1 | const firebaseConfig = {
2 | apiKey: process.env.REACT_APP_API_KEY,
3 | authDomain: process.env.REACT_APP_AUTH_DOMAIN,
4 | projectId: process.env.REACT_APP_PROJECT_ID,
5 | storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
6 | messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
7 | appId: process.env.REACT_APP_APP_ID,
8 | };
9 | export default firebaseConfig;
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/src/contexts/AuthProvider/AuthProvider.js:
--------------------------------------------------------------------------------
1 | import React, { createContext } from 'react';
2 | import useFirebase from './../../hooks/useFirebase';
3 |
4 | export const AuthContext = createContext(null);
5 |
6 | const AuthProvider = ({ children }) => {
7 | const allContexts = useFirebase();
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
15 | export default AuthProvider;
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import reportWebVitals from './reportWebVitals';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/src/Pages/Home/Home/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Navigation from '../../Shared/Navigation/Navigation';
3 | import AppointmentBanner from '../AppointmentBanner/AppointmentBanner';
4 | import Banner from '../Banner/Banner';
5 | import Services from '../Services/Services';
6 |
7 | const Home = () => {
8 | return (
9 |
15 | );
16 | };
17 |
18 | export default Home;
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/Pages/Appointment/Appointment/Appointment.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Navigation from '../../Shared/Navigation/Navigation';
3 | import AppointmentHeader from '../AppointmentHeader/AppointmentHeader';
4 | import AvailableAppointments from '../AvailableAppointments/AvailableAppointments';
5 |
6 | const Appointment = () => {
7 | const [date, setDate] = React.useState(new Date());
8 | return (
9 |
14 | );
15 | };
16 |
17 | export default Appointment;
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Pages/Appointment/AppointmentHeader/AppointmentHeader.js:
--------------------------------------------------------------------------------
1 | import { Container, Grid } from '@mui/material';
2 | import React from 'react';
3 | import chair from '../../../images/chair.png';
4 | import Calendar from '../../Shared/Calendar/Calendar';
5 |
6 | const AppointmentHeader = ({ date, setDate }) => {
7 |
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | );
20 | };
21 |
22 | export default AppointmentHeader;
--------------------------------------------------------------------------------
/src/Pages/Dashboard/DashboardHome/DashboardHome.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Grid from '@mui/material/Grid';
3 | import Calendar from '../../Shared/Calendar/Calendar';
4 | import Appointments from '../Appointments/Appointments';
5 |
6 | const DashboardHome = () => {
7 | const [date, setDate] = React.useState(new Date())
8 | return (
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | };
22 |
23 | export default DashboardHome;
--------------------------------------------------------------------------------
/src/Pages/Shared/Calendar/Calendar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TextField from '@mui/material/TextField';
3 | import AdapterDateFns from '@mui/lab/AdapterDateFns';
4 | import LocalizationProvider from '@mui/lab/LocalizationProvider';
5 | import StaticDatePicker from '@mui/lab/StaticDatePicker';
6 |
7 | const Calendar = ({ date, setDate }) => {
8 |
9 | return (
10 |
11 | {
15 | setDate(newValue);
16 | }}
17 | renderInput={(params) => }
18 | />
19 |
20 | );
21 | };
22 |
23 | export default Calendar;
--------------------------------------------------------------------------------
/src/Pages/Login/PrivateRoute/PrivateRoute.js:
--------------------------------------------------------------------------------
1 | import { CircularProgress } from '@mui/material';
2 | import React from 'react';
3 | import { Route, Redirect } from 'react-router-dom';
4 | import useAuth from './../../../hooks/useAuth';
5 |
6 | const PrivateRoute = ({ children, ...rest }) => {
7 | const { user, isLoading } = useAuth();
8 | if (isLoading) { return }
9 | return (
10 |
13 | user.email ? (
14 | children
15 | ) : (
16 |
22 | )
23 | }
24 | />
25 | );
26 | };
27 |
28 | export default PrivateRoute;
--------------------------------------------------------------------------------
/src/Pages/Login/AdminRoute/AdminRoute.js:
--------------------------------------------------------------------------------
1 | import { CircularProgress } from '@mui/material';
2 | import React from 'react';
3 | import { Route, Redirect } from 'react-router-dom';
4 | import useAuth from './../../../hooks/useAuth';
5 |
6 | const AdminRoute = ({ children, ...rest }) => {
7 | const { user, admin, isLoading } = useAuth();
8 | if (isLoading) { return }
9 | return (
10 |
13 | user.email && admin ? (
14 | children
15 | ) : (
16 |
22 | )
23 | }
24 | />
25 | );
26 | };
27 |
28 | export default AdminRoute;
--------------------------------------------------------------------------------
/src/Pages/Home/Service/Service.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Grid from '@mui/material/Grid';
3 | import Card from '@mui/material/Card';
4 | import CardContent from '@mui/material/CardContent';
5 | import CardMedia from '@mui/material/CardMedia';
6 | import Typography from '@mui/material/Typography';
7 |
8 | const Service = (props) => {
9 | const { name, description, img } = props.service;
10 | return (
11 |
12 |
13 |
19 |
20 |
21 | {name}
22 |
23 |
24 | {description}
25 |
26 |
27 |
28 |
29 | );
30 | };
31 |
32 | export default Service;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "doctors-portal-client",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emotion/react": "^11.5.0",
7 | "@emotion/styled": "^11.3.0",
8 | "@mui/icons-material": "^5.0.5",
9 | "@mui/lab": "^5.0.0-alpha.53",
10 | "@mui/material": "^5.0.6",
11 | "@testing-library/jest-dom": "^5.11.4",
12 | "@testing-library/react": "^11.1.0",
13 | "@testing-library/user-event": "^12.1.10",
14 | "date-fns": "^2.25.0",
15 | "firebase": "^9.2.0",
16 | "react": "^17.0.2",
17 | "react-dom": "^17.0.2",
18 | "react-router-dom": "^5.3.0",
19 | "react-scripts": "4.0.3",
20 | "web-vitals": "^1.0.1"
21 | },
22 | "scripts": {
23 | "start": "react-scripts start",
24 | "build": "react-scripts build",
25 | "test": "react-scripts test",
26 | "eject": "react-scripts eject"
27 | },
28 | "eslintConfig": {
29 | "extends": [
30 | "react-app",
31 | "react-app/jest"
32 | ]
33 | },
34 | "browserslist": {
35 | "production": [
36 | ">0.2%",
37 | "not dead",
38 | "not op_mini all"
39 | ],
40 | "development": [
41 | "last 1 chrome version",
42 | "last 1 firefox version",
43 | "last 1 safari version"
44 | ]
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Pages/Login/Login/Firebase/firebase.init.js:
--------------------------------------------------------------------------------
1 | import { initializeApp } from "firebase/app";
2 | import firebaseConfig from './firebase.config';
3 |
4 | const initializeFirebase = () => {
5 | initializeApp(firebaseConfig);
6 | }
7 |
8 | export default initializeFirebase;
9 |
10 | /*
11 | steps for authentication
12 | ----------------
13 | Step-1: Initial Setup
14 | 1. firebase: create project
15 | 2. create web app
16 | 3. get configuration
17 | 4. initialize firebase
18 | 5. Enable auth method
19 | ------------------
20 | Step-2: setup component
21 | 1. Create Login Component
22 | 2. Create Register Component
23 | 3. Create Route for Login and Register
24 | ------------------------
25 | Step 3: set auth system
26 | 1. set up sign in method
27 | 2. setup sign out method
28 | 3. user state
29 | 4. special observer
30 | 5. return necessary methods and states from useFirebase
31 | ---------------------
32 | Step 4: create auth context hook (useAuth)
33 | 1. create a auth context
34 | 2. Create context Provider
35 | 3. set context Provider context value
36 | 4. use Auth Provider in the app.js
37 | 5. create useAuth Hook
38 | ---------------------
39 | Step 5: create private route
40 | 1. create private Route
41 | 2. set private route
42 | ------------------
43 | Step-6: Redirect after login
44 | 1. after login redirect user to their desired destination
45 | */
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import {
3 | BrowserRouter as Router,
4 | Switch,
5 | Route
6 | } from "react-router-dom";
7 | import Home from './Pages/Home/Home/Home';
8 | import Appointment from './Pages/Appointment/Appointment/Appointment';
9 | import Login from './Pages/Login/Login/Login';
10 | import Register from './Pages/Login/Register/Register';
11 | import AuthProvider from './contexts/AuthProvider/AuthProvider';
12 | import PrivateRoute from './Pages/Login/PrivateRoute/PrivateRoute';
13 | import Dashboard from './Pages/Dashboard/Dashboard/Dashboard';
14 |
15 | function App() {
16 | return (
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | );
44 | }
45 |
46 | export default App;
47 |
--------------------------------------------------------------------------------
/src/Pages/Home/Banner/Banner.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Grid from '@mui/material/Grid';
3 | import chair from '../../../images/chair.png';
4 | import bg from '../../../images/bg.png';
5 | import { Typography, Button, Container } from '@mui/material';
6 | import Box from '@mui/material/Box';
7 |
8 |
9 | const bannerBg = {
10 | background: `url(${bg})`,
11 |
12 | }
13 |
14 | const verticalCenter = {
15 | display: 'flex',
16 | alignItems: 'center',
17 | height: 400
18 | }
19 |
20 | const Banner = () => {
21 | return (
22 |
23 |
24 |
25 |
26 |
27 | Your New Smile
28 | Starts Here
29 |
30 |
31 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil asperiores velit illum enim incidunt doloremque vitae impedit at accusantium tenetur.
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | );
43 | };
44 |
45 | export default Banner;
--------------------------------------------------------------------------------
/src/Pages/Dashboard/MakeAdmin/MakeAdmin.js:
--------------------------------------------------------------------------------
1 | import { Button, TextField, Alert } from '@mui/material';
2 | import React, { useState } from 'react';
3 | import useAuth from './../../../hooks/useAuth';
4 |
5 | const MakeAdmin = () => {
6 | const [email, setEmail] = useState('');
7 | const [success, setSuccess] = useState(false);
8 | const { token } = useAuth();
9 |
10 | const handleOnBlur = e => {
11 | setEmail(e.target.value);
12 | }
13 | const handleAdminSubmit = e => {
14 | const user = { email };
15 | fetch('https://stark-caverns-04377.herokuapp.com/users/admin', {
16 | method: 'PUT',
17 | headers: {
18 | 'authorization': `Bearer ${token}`,
19 | 'content-type': 'application/json'
20 | },
21 | body: JSON.stringify(user)
22 | })
23 | .then(res => res.json())
24 | .then(data => {
25 | if (data.modifiedCount) {
26 | console.log(data);
27 | setSuccess(true);
28 | }
29 | })
30 |
31 | e.preventDefault()
32 | }
33 | return (
34 |
35 |
Make an Admin
36 |
45 | {success &&
Made Admin successfully!}
46 |
47 | );
48 | };
49 |
50 | export default MakeAdmin;
--------------------------------------------------------------------------------
/src/Pages/Appointment/Booking/Booking.js:
--------------------------------------------------------------------------------
1 | import { Grid } from '@mui/material';
2 | import React from 'react';
3 | import Paper from '@mui/material/Paper';
4 | import Typography from '@mui/material/Typography';
5 | import Button from '@mui/material/Button';
6 | import BookingModal from '../BookingModal/BookingModal';
7 |
8 | const Booking = ({ booking, date, setBookingSuccess }) => {
9 | const { name, time, space } = booking;
10 | const [openBooking, setBookingOpen] = React.useState(false);
11 | const handleBookingOpen = () => setBookingOpen(true);
12 | const handleBookingClose = () => setBookingOpen(false);
13 | return (
14 | <>
15 |
16 |
17 |
18 | {name}
19 |
20 |
21 | {time}
22 |
23 |
24 | {space} SPACES AVAILABLE
25 |
26 |
27 |
28 |
29 |
36 | >
37 | );
38 | };
39 |
40 | export default Booking;
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
16 |
17 |
26 | React App
27 |
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/Pages/Appointment/AvailableAppointments/AvailableAppointments.js:
--------------------------------------------------------------------------------
1 | import { Container, Grid, Typography, Alert } from '@mui/material';
2 | import React, { useState } from 'react';
3 | import Booking from '../Booking/Booking';
4 |
5 | const bookings = [
6 | {
7 | id: 1,
8 | name: 'Teeth Orthodonics',
9 | time: '08.00 AM - 09.00 AM',
10 | space: 10,
11 | },
12 | {
13 | id: 2,
14 | name: 'Cosmetic Dentistry',
15 | time: '09.00 AM - 10.00 AM',
16 | space: 8,
17 | },
18 | {
19 | id: 3,
20 | name: 'Teeth Cleaning',
21 | time: '10.00 AM - 11.00 AM',
22 | space: 9,
23 | },
24 | {
25 | id: 4,
26 | name: 'Cavity Protection',
27 | time: '11.00 AM - 12.00 PM',
28 | space: 5,
29 | },
30 | {
31 | id: 5,
32 | name: 'Pediatric Dental',
33 | time: '06.00 PM - 07.00 PM',
34 | space: 10,
35 | },
36 | {
37 | id: 6,
38 | name: 'Oral Surgery',
39 | time: '07.00 PM - 08.00 PM',
40 | space: 10,
41 | },
42 | ]
43 |
44 | const AvailableAppointments = ({ date }) => {
45 | const [bookingSuccess, setBookingSuccess] = useState(false);
46 | return (
47 |
48 | Available Appointments on {date.toDateString()}
49 | {bookingSuccess && Appointment Booked successfully!}
50 |
51 | {
52 | bookings.map(booking =>
58 | )
59 | }
60 |
61 |
62 | );
63 | };
64 |
65 | export default AvailableAppointments;
--------------------------------------------------------------------------------
/src/Pages/Home/AppointmentBanner/AppointmentBanner.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Box from '@mui/material/Box';
3 | import Grid from '@mui/material/Grid';
4 | import doctor from '../../../images/doctor.png'
5 | import bg from '../../../images/appointment-bg.png'
6 | import { Button, Typography } from '@mui/material';
7 |
8 | const appointmentBanner = {
9 | background: `url(${bg})`,
10 | backgroundColor: 'rgba(45, 58, 74, 0.9)',
11 | backgroundBlendMode: 'darken, luminosity',
12 | marginTop: 175
13 | }
14 |
15 | const AppointmentBanner = () => {
16 | return (
17 |
18 |
19 |
20 |
23 |
24 |
30 |
31 |
32 | Appointment
33 |
34 |
35 | Make an Appointment Today
36 |
37 |
38 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Sequi facere totam aliquam praesentium vel. Amet veniam odio vero doloremque laborum.
39 |
40 |
41 |
42 |
43 |
44 |
45 | );
46 | };
47 |
48 | export default AppointmentBanner;
--------------------------------------------------------------------------------
/src/Pages/Shared/Navigation/Navigation.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AppBar from '@mui/material/AppBar';
3 | import Box from '@mui/material/Box';
4 | import Toolbar from '@mui/material/Toolbar';
5 | import Typography from '@mui/material/Typography';
6 | import Button from '@mui/material/Button';
7 | import IconButton from '@mui/material/IconButton';
8 | import MenuIcon from '@mui/icons-material/Menu';
9 | import { Link, NavLink } from 'react-router-dom';
10 | import useAuth from './../../../hooks/useAuth';
11 |
12 | const Navigation = () => {
13 | const { user, logout } = useAuth();
14 | return (
15 |
16 |
17 |
18 |
25 |
26 |
27 |
28 | Doctors Portal
29 |
30 |
31 | {
32 | user?.email ?
33 |
34 |
35 |
36 |
37 |
38 |
39 | :
40 |
41 |
42 |
43 | }
44 |
45 |
46 |
47 | );
48 | };
49 |
50 | export default Navigation;
--------------------------------------------------------------------------------
/src/Pages/Home/Services/Services.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Box from '@mui/material/Box';
3 | import Grid from '@mui/material/Grid';
4 | import { Container } from '@mui/material';
5 | import Typography from '@mui/material/Typography';
6 | import Service from './../Service/Service';
7 | import fluoride from '../../../images/fluoride.png';
8 | import cavity from '../../../images/cavity.png';
9 | import whitening from '../../../images/whitening.png';
10 |
11 | const services = [
12 | {
13 | name: 'Fluoride Treatment',
14 | description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed culpa cumque enim! Voluptatibus aliquid expedita saepe accusantium itaque ducimus rem voluptas',
15 | img: fluoride
16 | },
17 | {
18 | name: 'Cavity Filling',
19 | description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed culpa cumque enim! Voluptatibus aliquid expedita saepe accusantium itaque ducimus rem voluptas',
20 | img: cavity
21 | },
22 | {
23 | name: 'Teeth Whitening',
24 | description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed culpa cumque enim! Voluptatibus aliquid expedita saepe accusantium itaque ducimus rem voluptas',
25 | img: whitening
26 | }
27 | ]
28 |
29 |
30 | const Services = () => {
31 | return (
32 |
33 |
34 |
35 | OUR SERVICES
36 |
37 |
38 | Services We Provide
39 |
40 |
41 | {
42 | services.map(service => )
46 | }
47 |
48 |
49 |
50 | );
51 | };
52 |
53 | export default Services;
--------------------------------------------------------------------------------
/.firebase/hosting.YnVpbGQ.cache:
--------------------------------------------------------------------------------
1 | favicon.ico,1631164518270,eae62e993eb980ec8a25058c39d5a51feab118bd2100c4deebb2a9c158ec11f9
2 | logo192.png,1631164518270,3ee59515172ee198f3be375979df15ac5345183e656720a381b8872b2a39dc8b
3 | logo512.png,1631164518270,ee7e2f3fdb8209c4b6fd7bef6ba50d1b9dba30a25bb5c3126df057e1cb6f5331
4 | manifest.json,1631164518270,aff3449bdc238776f5d6d967f19ec491b36aed5fb7f23ccff6500736fd58494a
5 | robots.txt,1631164518270,bfe106a3fb878dc83461c86818bf74fc1bdc7f28538ba613cd3e775516ce8b49
6 | asset-manifest.json,1636173510213,6cedf178cdd8b4fc096c7befebbb56f91098cc64a106af91ff532bef49635fe7
7 | index.html,1636173510213,73b3737a636c5293d0edadb00cc520ee00f21f5d02698ace31aeb10902183da7
8 | static/css/main.8c8b27cf.chunk.css,1636173510185,850bc16f7678f79f886c9febec0b79034002882ca68aeb13470b574d81dac66a
9 | static/js/2.14c62c4b.chunk.js.LICENSE.txt,1636173510208,ec91ea60d1a89e69d0722d8482fbf29c1932632de4565ddc2135e561b07d9b84
10 | static/css/main.8c8b27cf.chunk.css.map,1636173510209,4328ed535cb7dddf41685d7de12d64bd6864c881392ce1c400e9cbeb8a7e6b82
11 | static/js/3.7cb1c5f7.chunk.js,1636173510209,7c61f4191bb05d5312ac7a42291028696d0de31d1a42bcdc8d1075af2ae7dfc0
12 | static/js/3.7cb1c5f7.chunk.js.map,1636173510216,80863fa5a72c795375babb72a7a469343353a5ac40b524ce7df2e18201c0eb30
13 | static/js/runtime-main.dfa07f1c.js,1636173510208,fd08edb04ad4cf19578ab28a08c1c8d68b7c4f17018047eedeeb50423480a6b9
14 | static/js/main.b7623d66.chunk.js,1636173510190,5882f300f9169c807f9213e9e355add3fb1c8aad865ddb9abf892f1ef2f5a3ea
15 | static/js/runtime-main.dfa07f1c.js.map,1636173510209,e8171446be06133828758e06f872f4bf1e03e19d69fc3a86eeb302a6dddc48f1
16 | static/js/main.b7623d66.chunk.js.map,1636173510209,2f95a715b618602dc9dfba80bb780d69536b08b325fd7d835b788363bf20d979
17 | static/media/login.fe92a7a6.png,1636173510208,32e541a958f3b4845de7f1960e5ea2df5a5704120d39fa10ead9fa66a0f01cde
18 | static/media/doctor.0a279a5b.png,1636173510177,698eeae22f6b6b64b592b5dc2bcbdd0862d167718a3282cb2bdcc552d3eea758
19 | static/media/chair.3ca333d1.png,1636173510208,b612eade861cff5c89df42505ca28ff4a698e1439a7703e8d4fefd69e3fdf672
20 | static/media/bg.33b42bf9.png,1636173510208,3f049762b651db5bf54da4c48abe86092382bf2d7b61a6c600fe9c1913f99d6e
21 | static/js/2.14c62c4b.chunk.js,1636173510209,ad30e87ff33a1640bc90447646ac80394a9a4f730a2f36a03bece0e10adf0bac
22 | static/media/appointment-bg.eb42256e.png,1636173510209,7afd485c63cd091f9a57d62b240fe44f98bf6385615c8eabdbf5e368acab6a48
23 | static/js/2.14c62c4b.chunk.js.map,1636173510212,4f5a86c22841464ed77d8538f23ea7b42de988bb81dc0f7ee659727ab1806be5
24 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Pages/Dashboard/Appointments/Appointments.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import useAuth from './../../../hooks/useAuth';
3 | import Table from '@mui/material/Table';
4 | import TableBody from '@mui/material/TableBody';
5 | import TableCell from '@mui/material/TableCell';
6 | import TableContainer from '@mui/material/TableContainer';
7 | import TableHead from '@mui/material/TableHead';
8 | import TableRow from '@mui/material/TableRow';
9 | import Paper from '@mui/material/Paper';
10 |
11 | const Appointments = ({ date }) => {
12 | const { user, token } = useAuth();
13 | const [appointments, setAppointments] = useState([])
14 |
15 | useEffect(() => {
16 | const url = `https://stark-caverns-04377.herokuapp.com/appointments?email=${user.email}&date=${date.toLocaleDateString()}`
17 | fetch(url, {
18 | headers: {
19 | 'authorization': `Bearer ${token}`
20 | }
21 | })
22 | .then(res => res.json())
23 | .then(data => setAppointments(data));
24 | }, [date, user.email, token])
25 |
26 | return (
27 |
28 |
Appointments: {appointments.length}
29 |
30 |
31 |
32 |
33 | Name
34 | Time
35 | Service
36 | Action
37 |
38 |
39 |
40 | {appointments.map((row) => (
41 |
45 |
46 | {row.patientName}
47 |
48 | {row.time}
49 | {row.serviceName}
50 | {row.fat}
51 |
52 | ))}
53 |
54 |
55 |
56 |
57 | );
58 | };
59 |
60 | export default Appointments;
--------------------------------------------------------------------------------
/src/Pages/Login/Login/Login.js:
--------------------------------------------------------------------------------
1 | import { Container, Typography, TextField, Button, CircularProgress, Alert } from '@mui/material';
2 | import React, { useState } from 'react';
3 | import { Grid } from '@mui/material';
4 | import login from '../../../images/login.png'
5 | import { NavLink, useLocation, useHistory } from 'react-router-dom';
6 | import useAuth from './../../../hooks/useAuth';
7 |
8 | const Login = () => {
9 | const [loginData, setLoginData] = useState({});
10 | const { user, loginUser, signInWithGoogle, isLoading, authError } = useAuth();
11 |
12 | const location = useLocation();
13 | const history = useHistory();
14 |
15 | const handleOnChange = e => {
16 | const field = e.target.name;
17 | const value = e.target.value;
18 | const newLoginData = { ...loginData };
19 | newLoginData[field] = value;
20 | setLoginData(newLoginData);
21 | }
22 | const handleLoginSubmit = e => {
23 | loginUser(loginData.email, loginData.password, location, history);
24 | e.preventDefault();
25 | }
26 |
27 | const handleGoogleSignIn = () => {
28 | signInWithGoogle(location, history)
29 | }
30 | return (
31 |
32 |
33 |
34 | Login
35 |
62 | ------------------------
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | );
71 | };
72 |
73 | export default Login;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `yarn start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `yarn test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `yarn build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `yarn eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35 |
36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39 |
40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `yarn build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/src/Pages/Login/Register/Register.js:
--------------------------------------------------------------------------------
1 | import { Container, Typography, TextField, Button, CircularProgress, Alert } from '@mui/material';
2 | import React, { useState } from 'react';
3 | import { Grid } from '@mui/material';
4 | import login from '../../../images/login.png'
5 | import { NavLink, useHistory } from 'react-router-dom';
6 | import useAuth from './../../../hooks/useAuth';
7 |
8 | const Register = () => {
9 | const [loginData, setLoginData] = useState({});
10 | const history = useHistory();
11 | const { user, registerUser, isLoading, authError } = useAuth();
12 |
13 | const handleOnBlur = e => {
14 | const field = e.target.name;
15 | const value = e.target.value;
16 | const newLoginData = { ...loginData };
17 | newLoginData[field] = value;
18 | setLoginData(newLoginData);
19 | }
20 | const handleLoginSubmit = e => {
21 | if (loginData.password !== loginData.password2) {
22 | alert('Your password did not match');
23 | return
24 | }
25 | registerUser(loginData.email, loginData.password, loginData.name, history);
26 | e.preventDefault();
27 | }
28 | return (
29 |
30 |
31 |
32 | Register
33 | {!isLoading && }
73 | {isLoading && }
74 | {user?.email && User Created successfully!}
75 | {authError && {authError}}
76 |
77 |
78 |
79 |
80 |
81 |
82 | );
83 | };
84 |
85 | export default Register;
--------------------------------------------------------------------------------
/src/hooks/useFirebase.js:
--------------------------------------------------------------------------------
1 | import initializeFirebase from "../Pages/Login/Login/Firebase/firebase.init";
2 | import { useState, useEffect } from 'react';
3 | import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, GoogleAuthProvider, signInWithPopup, updateProfile, getIdToken, signOut } from "firebase/auth";
4 |
5 |
6 | // initialize firebase app
7 | initializeFirebase();
8 |
9 | const useFirebase = () => {
10 | const [user, setUser] = useState({});
11 | const [isLoading, setIsLoading] = useState(true);
12 | const [authError, setAuthError] = useState('');
13 | const [admin, setAdmin] = useState(false);
14 | const [token, setToken] = useState('');
15 |
16 | const auth = getAuth();
17 | const googleProvider = new GoogleAuthProvider();
18 |
19 | const registerUser = (email, password, name, history) => {
20 | setIsLoading(true);
21 | createUserWithEmailAndPassword(auth, email, password)
22 | .then((userCredential) => {
23 | setAuthError('');
24 | const newUser = { email, displayName: name };
25 | setUser(newUser);
26 | // save user to the database
27 | saveUser(email, name, 'POST');
28 | // send name to firebase after creation
29 | updateProfile(auth.currentUser, {
30 | displayName: name
31 | }).then(() => {
32 | }).catch((error) => {
33 | });
34 | history.replace('/');
35 | })
36 | .catch((error) => {
37 | setAuthError(error.message);
38 | console.log(error);
39 | })
40 | .finally(() => setIsLoading(false));
41 | }
42 |
43 | const loginUser = (email, password, location, history) => {
44 | setIsLoading(true);
45 | signInWithEmailAndPassword(auth, email, password)
46 | .then((userCredential) => {
47 | const destination = location?.state?.from || '/';
48 | history.replace(destination);
49 | setAuthError('');
50 | })
51 | .catch((error) => {
52 | setAuthError(error.message);
53 | })
54 | .finally(() => setIsLoading(false));
55 | }
56 |
57 | const signInWithGoogle = (location, history) => {
58 | setIsLoading(true);
59 | signInWithPopup(auth, googleProvider)
60 | .then((result) => {
61 | const user = result.user;
62 | saveUser(user.email, user.displayName, 'PUT');
63 | setAuthError('');
64 | const destination = location?.state?.from || '/';
65 | history.replace(destination);
66 | }).catch((error) => {
67 | setAuthError(error.message);
68 | }).finally(() => setIsLoading(false));
69 | }
70 |
71 | // observer user state
72 | useEffect(() => {
73 | const unsubscribed = onAuthStateChanged(auth, (user) => {
74 | if (user) {
75 | setUser(user);
76 | getIdToken(user)
77 | .then(idToken => {
78 | setToken(idToken);
79 | })
80 | } else {
81 | setUser({})
82 | }
83 | setIsLoading(false);
84 | });
85 | return () => unsubscribed;
86 | }, [auth])
87 |
88 | useEffect(() => {
89 | fetch(`https://stark-caverns-04377.herokuapp.com/users/${user.email}`)
90 | .then(res => res.json())
91 | .then(data => setAdmin(data.admin))
92 | }, [user.email])
93 |
94 | const logout = () => {
95 | setIsLoading(true);
96 | signOut(auth).then(() => {
97 | // Sign-out successful.
98 | }).catch((error) => {
99 | // An error happened.
100 | })
101 | .finally(() => setIsLoading(false));
102 | }
103 |
104 | const saveUser = (email, displayName, method) => {
105 | const user = { email, displayName };
106 | fetch('https://stark-caverns-04377.herokuapp.com/users', {
107 | method: method,
108 | headers: {
109 | 'content-type': 'application/json'
110 | },
111 | body: JSON.stringify(user)
112 | })
113 | .then()
114 | }
115 |
116 | return {
117 | user,
118 | admin,
119 | token,
120 | isLoading,
121 | authError,
122 | registerUser,
123 | loginUser,
124 | signInWithGoogle,
125 | logout,
126 | }
127 | }
128 |
129 | export default useFirebase;
--------------------------------------------------------------------------------
/src/Pages/Appointment/BookingModal/BookingModal.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import Backdrop from '@mui/material/Backdrop';
3 | import Box from '@mui/material/Box';
4 | import Modal from '@mui/material/Modal';
5 | import Fade from '@mui/material/Fade';
6 | import Typography from '@mui/material/Typography';
7 | import TextField from '@mui/material/TextField';
8 | import Button from '@mui/material/Button';
9 | import useAuth from './../../../hooks/useAuth';
10 |
11 | const style = {
12 | position: 'absolute',
13 | top: '50%',
14 | left: '50%',
15 | transform: 'translate(-50%, -50%)',
16 | width: 400,
17 | bgcolor: 'background.paper',
18 | border: '2px solid #000',
19 | boxShadow: 24,
20 | p: 4,
21 | };
22 |
23 | const BookingModal = ({ openBooking, handleBookingClose, booking, date, setBookingSuccess }) => {
24 | const { name, time } = booking;
25 | const { user } = useAuth();
26 | const initialInfo = { patientName: user.displayName, email: user.email, phone: '' }
27 | const [bookingInfo, setBookingInfo] = useState(initialInfo);
28 |
29 | const handleOnBlur = e => {
30 | const field = e.target.name;
31 | const value = e.target.value;
32 | const newInfo = { ...bookingInfo };
33 | newInfo[field] = value;
34 | setBookingInfo(newInfo);
35 | }
36 |
37 | const handleBookingSubmit = e => {
38 | // collect data
39 | const appointment = {
40 | ...bookingInfo,
41 | time,
42 | serviceName: name,
43 | date: date.toLocaleDateString()
44 | }
45 | // send to the server
46 | fetch('https://stark-caverns-04377.herokuapp.com/appointments', {
47 | method: 'POST',
48 | headers: {
49 | 'content-type': 'application/json'
50 | },
51 | body: JSON.stringify(appointment)
52 | })
53 | .then(res => res.json())
54 | .then(data => {
55 | if (data.insertedId) {
56 | setBookingSuccess(true);
57 | handleBookingClose();
58 | }
59 | });
60 |
61 | e.preventDefault();
62 | }
63 |
64 | return (
65 |
76 |
77 |
78 |
79 | {name}
80 |
81 |
122 |
123 |
124 |
125 | );
126 | };
127 |
128 | export default BookingModal;
--------------------------------------------------------------------------------
/src/Pages/Dashboard/Dashboard/Dashboard.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import PropTypes from 'prop-types';
3 | import AppBar from '@mui/material/AppBar';
4 | import Box from '@mui/material/Box';
5 | import CssBaseline from '@mui/material/CssBaseline';
6 | import Divider from '@mui/material/Divider';
7 | import Drawer from '@mui/material/Drawer';
8 | import IconButton from '@mui/material/IconButton';
9 | import InboxIcon from '@mui/icons-material/MoveToInbox';
10 | import List from '@mui/material/List';
11 | import ListItem from '@mui/material/ListItem';
12 | import ListItemIcon from '@mui/material/ListItemIcon';
13 | import ListItemText from '@mui/material/ListItemText';
14 | import MailIcon from '@mui/icons-material/Mail';
15 | import MenuIcon from '@mui/icons-material/Menu';
16 | import Toolbar from '@mui/material/Toolbar';
17 | import Typography from '@mui/material/Typography';
18 | import {
19 | Switch,
20 | Route,
21 | Link,
22 | useRouteMatch
23 | } from "react-router-dom";
24 | import { Button } from '@mui/material';
25 | import DashboardHome from '../DashboardHome/DashboardHome';
26 | import MakeAdmin from '../MakeAdmin/MakeAdmin';
27 | import AddDoctor from '../AddDoctor/AddDoctor';
28 | import useAuth from './../../../hooks/useAuth';
29 | import AdminRoute from './../../Login/AdminRoute/AdminRoute';
30 |
31 | const drawerWidth = 200;
32 |
33 | function Dashboard(props) {
34 | const { window } = props;
35 | const [mobileOpen, setMobileOpen] = React.useState(false);
36 | let { path, url } = useRouteMatch();
37 | const { admin } = useAuth();
38 | const handleDrawerToggle = () => {
39 | setMobileOpen(!mobileOpen);
40 | };
41 |
42 | const drawer = (
43 |
44 |
45 |
46 |
47 |
48 | {admin &&
49 |
50 |
51 | }
52 |
53 | {['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
54 |
55 |
56 | {index % 2 === 0 ? : }
57 |
58 |
59 |
60 | ))}
61 |
62 |
63 | );
64 |
65 | const container = window !== undefined ? () => window().document.body : undefined;
66 |
67 | return (
68 |
69 |
70 |
77 |
78 |
85 |
86 |
87 |
88 | Dashboard
89 |
90 |
91 |
92 |
97 |
110 | {drawer}
111 |
112 |
120 | {drawer}
121 |
122 |
123 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | );
144 | }
145 |
146 | Dashboard.propTypes = {
147 | /**
148 | * Injected by the documentation to work in an iframe.
149 | * You won't need it on your project.
150 | */
151 | window: PropTypes.func,
152 | };
153 |
154 | export default Dashboard;
155 |
--------------------------------------------------------------------------------