├── README.md ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json ├── index.html └── services.json ├── src ├── assets │ ├── images │ │ ├── bg.png │ │ ├── chair.png │ │ ├── login.png │ │ ├── cavity.png │ │ ├── doctor.png │ │ ├── footer.png │ │ ├── people1.png │ │ ├── people2.png │ │ ├── people3.png │ │ ├── shubham.jpg │ │ ├── dribbble_1.gif │ │ ├── fluoride.png │ │ ├── treatment.png │ │ ├── whitening.png │ │ ├── appointment.png │ │ └── doctor-small.png │ └── icons │ │ ├── marker.svg │ │ ├── quote.svg │ │ ├── phone.svg │ │ └── clock.svg ├── App.css ├── pages │ ├── Dashboard │ │ ├── MyReview │ │ │ └── MyReview.js │ │ ├── Dashboard │ │ │ ├── UsersRow │ │ │ │ └── UsersRow.js │ │ │ └── Dashboard.js │ │ ├── Users │ │ │ └── Users.js │ │ └── MyAppointments │ │ │ └── MyAppointments.js │ ├── Shared │ │ ├── Theme │ │ │ ├── Background │ │ │ │ └── Background.js │ │ │ └── ThemeToggle │ │ │ │ └── ThemeToggle.js │ │ ├── Loading │ │ │ └── Loading.js │ │ ├── CustomButton │ │ │ └── CustomButton.js │ │ ├── Navbar │ │ │ └── Navbar.js │ │ └── Footer │ │ │ └── Footer.js │ ├── Home │ │ ├── Info │ │ │ ├── InfoCard.js │ │ │ └── Info.js │ │ ├── Service │ │ │ └── Service.js │ │ ├── Home │ │ │ └── Home.js │ │ ├── Review │ │ │ └── Review.js │ │ ├── Banner │ │ │ └── Banner.js │ │ ├── Exceptional │ │ │ └── Exceptional.js │ │ ├── Services │ │ │ └── Services.js │ │ ├── MakeAppointment │ │ │ └── MakeAppointment.js │ │ ├── Contact │ │ │ └── Contact.js │ │ ├── Testimonials │ │ │ └── Testimonials.js │ │ └── Features │ │ │ └── Features.js │ ├── Appointment │ │ ├── Appointment │ │ │ └── Appointment.js │ │ ├── AppointmentBanner │ │ │ └── AppointmentBanner.js │ │ ├── Service │ │ │ └── Service.js │ │ ├── AvailableAppointments │ │ │ └── AvailableAppointments.js │ │ └── BookingModal │ │ │ └── BookingModal.js │ ├── Login │ │ ├── RequireAuth.js │ │ ├── RequireAdmin.js │ │ └── Login.js │ ├── About │ │ └── About.js │ └── Signup │ │ └── Signup.js ├── setupTests.js ├── App.test.js ├── reportWebVitals.js ├── index.css ├── firebase │ └── Firebase.init.js ├── hooks │ ├── useAdmin.js │ └── useToken.js ├── index.js ├── ThemeContext │ └── ThemeContext.js ├── logo.svg └── App.js ├── .gitignore ├── tailwind.config.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # 🚖 Hazrat Ali 2 | 3 | # 🚘 Programmer || Software Engineering 4 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/assets/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/bg.png -------------------------------------------------------------------------------- /src/assets/images/chair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/chair.png -------------------------------------------------------------------------------- /src/assets/images/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/login.png -------------------------------------------------------------------------------- /src/assets/images/cavity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/cavity.png -------------------------------------------------------------------------------- /src/assets/images/doctor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/doctor.png -------------------------------------------------------------------------------- /src/assets/images/footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/footer.png -------------------------------------------------------------------------------- /src/assets/images/people1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/people1.png -------------------------------------------------------------------------------- /src/assets/images/people2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/people2.png -------------------------------------------------------------------------------- /src/assets/images/people3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/people3.png -------------------------------------------------------------------------------- /src/assets/images/shubham.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/shubham.jpg -------------------------------------------------------------------------------- /src/assets/images/dribbble_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/dribbble_1.gif -------------------------------------------------------------------------------- /src/assets/images/fluoride.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/fluoride.png -------------------------------------------------------------------------------- /src/assets/images/treatment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/treatment.png -------------------------------------------------------------------------------- /src/assets/images/whitening.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/whitening.png -------------------------------------------------------------------------------- /src/assets/images/appointment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/appointment.png -------------------------------------------------------------------------------- /src/assets/images/doctor-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hazrat-Ali9/Doctors-Portal-Client/HEAD/src/assets/images/doctor-small.png -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | /* html,body{ 7 | margin: 0; 8 | padding: 0; 9 | 10 | } */ -------------------------------------------------------------------------------- /src/pages/Dashboard/MyReview/MyReview.js: -------------------------------------------------------------------------------- 1 | // My Review 2 | import React from 'react'; 3 | 4 | const MyReview = () => { 5 | return ( 6 |
7 | my review is here 8 |
9 | ); 10 | }; 11 | 12 | export default MyReview; -------------------------------------------------------------------------------- /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 | // setup tests 7 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | // app test 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/pages/Shared/Theme/Background/Background.js: -------------------------------------------------------------------------------- 1 | // Background 2 | import React from "react"; 3 | 4 | const Background = ({ children }) => { 5 | return ( 6 |
7 | {children} 8 |
9 | ); 10 | }; 11 | 12 | export default Background; -------------------------------------------------------------------------------- /src/pages/Shared/Loading/Loading.js: -------------------------------------------------------------------------------- 1 | // Loadings 2 | import React from "react"; 3 | 4 | const Loading = () => { 5 | return ( 6 |
7 |
8 |
9 | ); 10 | }; 11 | 12 | export default Loading; 13 | -------------------------------------------------------------------------------- /src/pages/Shared/CustomButton/CustomButton.js: -------------------------------------------------------------------------------- 1 | // Custom Button 2 | import React from "react"; 3 | 4 | const CustomButton = ({children}) => { 5 | return ( 6 | 9 | ); 10 | }; 11 | 12 | export default CustomButton; 13 | -------------------------------------------------------------------------------- /.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/assets/icons/marker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | // Report Web Vitals 2 | const reportWebVitals = onPerfEntry => { 3 | if (onPerfEntry && onPerfEntry instanceof Function) { 4 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 5 | getCLS(onPerfEntry); 6 | getFID(onPerfEntry); 7 | getFCP(onPerfEntry); 8 | getLCP(onPerfEntry); 9 | getTTFB(onPerfEntry); 10 | }); 11 | } 12 | }; 13 | 14 | export default reportWebVitals; 15 | 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | margin: 0; 7 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 8 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 9 | sans-serif; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | code { 15 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 16 | monospace; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: 'class', 4 | content: ["./src/**/*.{html,js}"], 5 | theme: { 6 | extend: {}, 7 | }, 8 | daisyui: { 9 | themes: [ 10 | { 11 | mytheme: { 12 | primary: "#0FCFEC", 13 | secondary: "#19D3AE", 14 | accent: "#3A4256", 15 | neutral: "#3d4451", 16 | "base-100": "#ffffff", 17 | }, 18 | }, 19 | "dark", 20 | "cupcake", 21 | ], 22 | }, 23 | plugins: [require("daisyui")], 24 | } 25 | 26 | // Tailwind Config -------------------------------------------------------------------------------- /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/Home/Info/InfoCard.js: -------------------------------------------------------------------------------- 1 | // Info Cards 2 | import React from "react"; 3 | 4 | const InfoCard = ({img, cardTitle, bgClass}) => { 5 | return ( 6 |
7 |
8 | Album 12 |
13 |
14 |

{cardTitle}

15 |

Click the button to listen on Spotiwhy app.

16 | 17 |
18 |
19 | ); 20 | }; 21 | 22 | export default InfoCard; 23 | -------------------------------------------------------------------------------- /src/pages/Home/Service/Service.js: -------------------------------------------------------------------------------- 1 | // Service 2 | import React from 'react'; 3 | 4 | const Service = ({service}) => { 5 | return ( 6 |
7 |
8 | Shoes 9 |
10 |
11 |

{service.name}

12 |

If a dog chews shoes whose shoes does he choose?

13 | 14 |
15 |
16 | ); 17 | }; 18 | 19 | export default Service; -------------------------------------------------------------------------------- /src/pages/Appointment/Appointment/Appointment.js: -------------------------------------------------------------------------------- 1 | // Appoinment 2 | import React from "react"; 3 | import Footer from "../../Shared/Footer/Footer"; 4 | import AppointmentBanner from "../AppointmentBanner/AppointmentBanner"; 5 | import { useState } from "react"; 6 | import AvailableAppointments from "../AvailableAppointments/AvailableAppointments"; 7 | 8 | const Appointment = () => { 9 | const [date, setDate] = useState(new Date()); 10 | return ( 11 |
12 | 13 | 14 |
15 |
16 | ); 17 | }; 18 | 19 | export default Appointment; 20 | -------------------------------------------------------------------------------- /src/pages/Login/RequireAuth.js: -------------------------------------------------------------------------------- 1 | // Require Auth 2 | import React from 'react'; 3 | import { useAuthState } from 'react-firebase-hooks/auth'; 4 | import {Navigate,useLocation} from 'react-router-dom'; 5 | import auth from '../../firebase/Firebase.init'; 6 | import Loading from '../Shared/Loading/Loading'; 7 | 8 | const RequireAuth = ({children}) => { 9 | const [user, loading] = useAuthState(auth); 10 | let location = useLocation(); 11 | 12 | if (loading) { 13 | return 14 | } 15 | 16 | if (!user) { 17 | return ; 18 | } 19 | 20 | return children; 21 | }; 22 | 23 | export default RequireAuth; -------------------------------------------------------------------------------- /src/pages/Home/Info/Info.js: -------------------------------------------------------------------------------- 1 | // Info 2 | import React from 'react'; 3 | import InfoCard from './InfoCard'; 4 | import clock from '../../../assets/icons/clock.svg'; 5 | import marker from '../../../assets/icons/marker.svg'; 6 | import phone from '../../../assets/icons/phone.svg'; 7 | 8 | const Info = () => { 9 | return ( 10 |
11 | 12 | 13 | 14 |
15 | ); 16 | }; 17 | 18 | export default Info; -------------------------------------------------------------------------------- /src/assets/icons/quote.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 7 | 8 | 9 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/firebase/Firebase.init.js: -------------------------------------------------------------------------------- 1 | // Import the functions you need from the SDKs you need 2 | import { initializeApp } from "firebase/app"; 3 | import { getAuth } from "firebase/auth"; 4 | // TODO: Add SDKs for Firebase products that you want to use 5 | // https://firebase.google.com/docs/web/setup#available-libraries 6 | // Firebase Init 7 | const firebaseConfig = { 8 | 9 | apiKey: import.meta.env.VITE_APIKEY, 10 | authDomain: import.meta.env.VITE_AUTHDOMAIN, 11 | projectId: import.meta.env.VITE_PROJECTID, 12 | storageBucket: import.meta.env.VITE_STORAGEBUCKET, 13 | messagingSenderId: import.meta.env.VITE_MESSAGINGSENDERID, 14 | appId: import.meta.env.VITE_APPID, 15 | 16 | }; 17 | 18 | 19 | 20 | 21 | // Initialize Firebase 22 | const app = initializeApp(firebaseConfig); 23 | 24 | const auth = getAuth(app); 25 | 26 | export default auth; 27 | -------------------------------------------------------------------------------- /src/pages/Home/Home/Home.js: -------------------------------------------------------------------------------- 1 | // Home 2 | import React from "react"; 3 | import Footer from "../../Shared/Footer/Footer"; 4 | import Banner from "../Banner/Banner"; 5 | import Contact from "../Contact/Contact"; 6 | import Exceptional from "../Exceptional/Exceptional"; 7 | import Features from "../Features/Features"; 8 | import Info from "../Info/Info"; 9 | import MakeAppointment from "../MakeAppointment/MakeAppointment"; 10 | import Services from "../Services/Services"; 11 | import Testimonials from "../Testimonials/Testimonials"; 12 | 13 | const Home = () => { 14 | return ( 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {/* */} 24 |
25 |
26 | ); 27 | }; 28 | 29 | export default Home; 30 | -------------------------------------------------------------------------------- /src/pages/Login/RequireAdmin.js: -------------------------------------------------------------------------------- 1 | // Require Admin 2 | import React from 'react'; 3 | import { useAuthState } from 'react-firebase-hooks/auth'; 4 | import {Navigate,useLocation} from 'react-router-dom'; 5 | import auth from '../../firebase/Firebase.init'; 6 | import Loading from '../Shared/Loading/Loading'; 7 | import useAdmin from './../../hooks/useAdmin'; 8 | import { signOut } from 'firebase/auth'; 9 | 10 | const RequireAdmin = ({children}) => { 11 | const [user, loading] = useAuthState(auth); 12 | const [admin, adminLoading] = useAdmin(user); 13 | let location = useLocation(); 14 | 15 | if (loading || adminLoading) { 16 | return 17 | } 18 | 19 | if (!user || !admin) { 20 | signOut(auth) 21 | return ; 22 | } 23 | 24 | return children; 25 | }; 26 | 27 | export default RequireAdmin; -------------------------------------------------------------------------------- /src/assets/icons/phone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/icons/clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/hooks/useAdmin.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { useEffect } from 'react'; 3 | // use admin 4 | const useAdmin = user => { 5 | const [admin, setAdmin] = useState(false); 6 | const [adminLoading, setAdminLoading] = useState(true); 7 | 8 | useEffect( () => { 9 | const email = user?.email; 10 | if(email) { 11 | fetch(`http://localhost:5000/admin/${email}`, { 12 | method:'GET', 13 | headers:{ 14 | 'content-type':'application/json', 15 | authorization:`Bearer ${localStorage.getItem('accessToken')}` 16 | }, 17 | }) 18 | .then(res => res.json()) 19 | .then(data => { 20 | setAdmin(data.admin); 21 | setAdminLoading(false); 22 | }) 23 | } 24 | },[user]) 25 | return [admin, adminLoading] 26 | }; 27 | 28 | export default useAdmin; -------------------------------------------------------------------------------- /src/pages/Appointment/AppointmentBanner/AppointmentBanner.js: -------------------------------------------------------------------------------- 1 | // Appoinment Banner 2 | import React from "react"; 3 | import chair from "../../../assets/images/chair.png"; 4 | import { DayPicker } from "react-day-picker"; 5 | import "react-day-picker/dist/style.css"; 6 | import appointmentBg from "../../../assets/images/bg.png"; 7 | 8 | const AppointmentBanner = ({ date, setDate }) => { 9 | return ( 10 |
17 |
18 | 19 |
20 | 21 |
22 |
23 |
24 | ); 25 | }; 26 | 27 | export default AppointmentBanner; 28 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Index js 2 | import React from "react"; 3 | import ReactDOM from "react-dom/client"; 4 | import "./index.css"; 5 | import App from "./App"; 6 | import reportWebVitals from "./reportWebVitals"; 7 | import { BrowserRouter as Router } from "react-router-dom"; 8 | import { ThemeContext } from "./ThemeContext/ThemeContext"; 9 | import { 10 | QueryClient, 11 | QueryClientProvider, 12 | } from "react-query"; 13 | // Query Client 14 | const queryClient = new QueryClient(); 15 | const root = ReactDOM.createRoot(document.getElementById("root")); 16 | root.render( 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | 26 | // If you want to start measuring performance in your app, pass a function 27 | // to log results (for example: reportWebVitals(console.log)) 28 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 29 | reportWebVitals(); 30 | -------------------------------------------------------------------------------- /src/hooks/useToken.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useState } from 'react'; 3 | import { useEffect } from 'react'; 4 | // user token 5 | const useToken = (user) => { 6 | const [token, setToken] = useState(''); 7 | 8 | useEffect(() => { 9 | const email = user?.user?.email; 10 | const currentUser = {email:email} 11 | if(email) { 12 | fetch(`http://localhost:5000/user/${email}`, { 13 | method:'PUT', 14 | header:{ 15 | 'content-type':'application/json', 16 | }, 17 | body:JSON.stringify(currentUser), 18 | }) 19 | .then(res => res.json()) 20 | .then(data => { 21 | console.log("data inside token", data); 22 | const accessToken = data.token; 23 | localStorage.setItem('accessToken', accessToken) 24 | setToken(accessToken); 25 | }) 26 | } 27 | },[user]) 28 | return [token]; 29 | }; 30 | 31 | export default useToken; -------------------------------------------------------------------------------- /src/pages/Home/Review/Review.js: -------------------------------------------------------------------------------- 1 | // Review 2 | import React from "react"; 3 | 4 | const Review = ({ review }) => { 5 | return ( 6 |
7 |
8 |

9 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Saepe 10 | eveniet omnis laboriosam adipisci beatae. Rerum nam quibusdam ad enim 11 | consequuntur. Lorem ipsum dolor sit amet consectetur adipisicing elit. 12 | Vero, natus. 13 |

14 |
15 |
16 |
17 | review.img 18 |
19 |
20 |
21 |

{review.name}

22 |

{review.location}

23 |
24 |
25 |
26 |
27 | ); 28 | }; 29 | 30 | export default Review; 31 | -------------------------------------------------------------------------------- /src/pages/Shared/Theme/ThemeToggle/ThemeToggle.js: -------------------------------------------------------------------------------- 1 | // Theme Toggle 2 | import React from 'react'; 3 | import { FaSun, FaMoon} from "react-icons/fa"; 4 | import { ThemeContext } from '../../../../ThemeContext/ThemeContext'; 5 | 6 | // React context 7 | const Toggle = () => { 8 | const { theme, setTheme } = React.useContext(ThemeContext); 9 | 10 | return ( 11 |
12 | {theme === 'dark' ? ( 13 | setTheme(theme === 'dark' ? 'light' : 'dark')} 15 | className="text-gray-500 dark:text-gray-400 text-2xl cursor-pointer lg:w-full lg:h-full" 16 | /> 17 | ) : ( 18 | setTheme(theme === 'dark' ? 'light' : 'dark')} 20 | className="text-gray-500 dark:text-gray-400 text-2xl cursor-pointer lg:w-full lg:h-full" 21 | /> 22 | )} 23 |
24 | ); 25 | }; 26 | 27 | export default Toggle; -------------------------------------------------------------------------------- /src/pages/Home/Banner/Banner.js: -------------------------------------------------------------------------------- 1 | // Banner 2 | import React from "react"; 3 | import chair from "../../../assets/images/chair.png"; 4 | import bannerBg from "../../../assets/images/bg.png"; 5 | import CustomButton from "../../Shared/CustomButton/CustomButton"; 6 | 7 | const Banner = () => { 8 | return ( 9 |
15 |
16 | 17 |
18 |

Your new smile starts here

19 |

20 | Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda 21 | excepturi exercitationem quasi. In deleniti eaque aut repudiandae et 22 | a id nisi. 23 |

24 | Get started 25 |
26 |
27 |
28 | ); 29 | }; 30 | 31 | export default Banner; 32 | -------------------------------------------------------------------------------- /src/pages/Appointment/Service/Service.js: -------------------------------------------------------------------------------- 1 | // Service 2 | import React from "react"; 3 | 4 | const Service = ({ service, setTreatment }) => { 5 | const { name, slots } = service; 6 | return ( 7 |
8 |
9 |

{name}

10 |

11 | {slots.length ? ( 12 | {slots[0]} 13 | ) : ( 14 | No slots available 15 | )} 16 |

17 |

18 | {slots.length} {slots.length > 1 ? "spaces" : "space"} 19 |

20 |
21 | 29 |
30 |
31 |
32 | ); 33 | }; 34 | 35 | export default Service; 36 | -------------------------------------------------------------------------------- /src/pages/Dashboard/Dashboard/UsersRow/UsersRow.js: -------------------------------------------------------------------------------- 1 | // User Row 2 | import React from "react"; 3 | import { toast } from 'react-toastify'; 4 | 5 | const UsersRow = ({user, refetch, index}) => { 6 | const {email, role} = user; 7 | const makeAdmin = () => { 8 | fetch(`http://localhost:5000/user/admin/${email}`, { 9 | method:"PUT", 10 | headers:{ 11 | authorization:`Bearer ${localStorage.getItem('accessToken')}` 12 | } 13 | }) 14 | .then(res => { 15 | if(res.status === 403) { 16 | toast.error('Failed to make na admin'); 17 | } 18 | return res.json() 19 | }) 20 | .then(data => { 21 | if(data.modifiedCount > 0) { 22 | refetch(); 23 | toast.success('Successfully made an admin'); 24 | } 25 | }) 26 | } 27 | 28 | return ( 29 | 30 | {index + 1} 31 | {email} 32 | {role !== 'admin' && } 33 | 34 | 35 | ); 36 | }; 37 | 38 | export default UsersRow; 39 | -------------------------------------------------------------------------------- /src/pages/Home/Exceptional/Exceptional.js: -------------------------------------------------------------------------------- 1 | // Expceptional 2 | import React from "react"; 3 | import treatment from "../../../assets/images/treatment.png"; 4 | import CustomButton from "../../Shared/CustomButton/CustomButton"; 5 | 6 | const Exceptional = () => { 7 | return ( 8 | 9 |
10 |
11 |
12 |
13 | treatment.png 14 |
15 |
16 |
17 |

Exceptional Dental Cares, On Your Terms

18 |

Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quisquam distinctio dolore, rerum consequuntur amet recusandae repudiandae molestiae illo mollitia aliquam! Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste, eos? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Voluptates, optio.

19 | Let's start 20 |
21 |
22 |
23 |
24 |
25 | ); 26 | }; 27 | 28 | export default Exceptional; 29 | -------------------------------------------------------------------------------- /src/pages/Home/Services/Services.js: -------------------------------------------------------------------------------- 1 | // Services 2 | import React from "react"; 3 | import fluoride from "../../../assets/images/fluoride.png"; 4 | import cavity from "../../../assets/images/cavity.png"; 5 | import whitening from "../../../assets/images/whitening.png"; 6 | import Service from "../Service/Service"; 7 | 8 | const Services = () => { 9 | const services = [ 10 | { 11 | _id: 1, 12 | name: "Fluoride Treatment", 13 | description: "", 14 | img: fluoride, 15 | }, 16 | { 17 | _id: 2, 18 | name: "Cavity Filling", 19 | description: "", 20 | img: cavity, 21 | }, 22 | { 23 | _id: 3, 24 | name: "Teeth Whitening", 25 | description: "", 26 | img: whitening, 27 | }, 28 | ]; 29 | return ( 30 |
31 |
32 |

33 | Our Services 34 |

35 |

Services We Provide

36 |
37 |
38 | {services.map((service) => ( 39 | 40 | ))} 41 |
42 |
43 | ); 44 | }; 45 | 46 | export default Services; 47 | -------------------------------------------------------------------------------- /src/pages/Dashboard/Dashboard/Dashboard.js: -------------------------------------------------------------------------------- 1 | // Dashboard 2 | import React from "react"; 3 | import { Link, Outlet } from "react-router-dom"; 4 | import useAdmin from './../../../hooks/useAdmin'; 5 | import { useAuthState } from 'react-firebase-hooks/auth'; 6 | import auth from './../../../firebase/Firebase.init'; 7 | 8 | const Dashboard = () => { 9 | const [user] = useAuthState(auth); 10 | const [admin] = useAdmin(user) 11 | 12 | return ( 13 |
14 | 15 |
16 |

Welcome to your Dashboard

17 | 18 |
19 | 20 |
21 | 22 |
    23 |
  • 24 | Dashboard 25 |
  • 26 |
  • 27 | My Review 28 |
  • 29 | {admin &&
  • 30 | All Users 31 |
  • } 32 |
33 |
34 |
35 | ); 36 | }; 37 | 38 | export default Dashboard; 39 | -------------------------------------------------------------------------------- /src/pages/Home/MakeAppointment/MakeAppointment.js: -------------------------------------------------------------------------------- 1 | // Appointment 2 | import React from "react"; 3 | import doctor from "../../../assets/images/doctor.png"; 4 | import appointment from "../../../assets/images/appointment.png"; 5 | import CustomButton from "../../Shared/CustomButton/CustomButton"; 6 | 7 | const MakeAppointment = () => { 8 | return ( 9 |
15 |
16 | doctor.png 17 |
18 |
19 |

Appointment

20 |

Make an appointment today

21 |

22 | Lorem, ipsum dolor sit amet consectetur adipisicing elit. Placeat 23 | asperiores esse voluptate consequatur delectus, voluptatibus tenetur 24 | reprehenderit similique quibusdam perferendis numquam consequuntur, 25 | maxime nemo iure voluptas est? Deserunt fuga culpa excepturi libero 26 | quis nam ab, officia eius nihil corrupti amet. 27 |

28 | Get started 29 |
30 |
31 | ); 32 | }; 33 | 34 | export default MakeAppointment; 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "doctors-portal-client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.3.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "aos": "^2.3.4", 10 | "daisyui": "^2.15.4", 11 | "date-fns": "^2.29.1", 12 | "firebase": "^9.8.3", 13 | "react": "^18.2.0", 14 | "react-day-picker": "^8.0.7", 15 | "react-dom": "^18.2.0", 16 | "react-firebase-hooks": "^5.0.3", 17 | "react-hook-form": "^7.32.1", 18 | "react-icons": "^4.4.0", 19 | "react-query": "^4.0.0", 20 | "react-router-dom": "^6.3.0", 21 | "react-scripts": "5.0.1", 22 | "react-toastify": "^9.0.8", 23 | "react-toggle-dark-mode": "^1.0.4", 24 | "web-vitals": "^2.1.4" 25 | }, 26 | "scripts": { 27 | "start": "react-scripts start", 28 | "build": "react-scripts build", 29 | "test": "react-scripts test", 30 | "eject": "react-scripts eject" 31 | }, 32 | "eslintConfig": { 33 | "extends": [ 34 | "react-app", 35 | "react-app/jest" 36 | ] 37 | }, 38 | "browserslist": { 39 | "production": [ 40 | ">0.2%", 41 | "not dead", 42 | "not op_mini all" 43 | ], 44 | "development": [ 45 | "last 1 chrome version", 46 | "last 1 firefox version", 47 | "last 1 safari version" 48 | ] 49 | }, 50 | "devDependencies": { 51 | "tailwindcss": "^3.1.3" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/ThemeContext/ThemeContext.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // Theme Context 3 | const getInitialTheme = () => { 4 | if (typeof window !== 'undefined' && window.localStorage) { 5 | const storedPrefs = window.localStorage.getItem('color-theme'); 6 | if (typeof storedPrefs === 'string') { 7 | return storedPrefs; 8 | } 9 | 10 | const userMedia = window.matchMedia('(prefers-color-scheme: dark)'); 11 | if (userMedia.matches) { 12 | return 'dark'; 13 | } 14 | } 15 | 16 | return 'light' // light theme as the default; 17 | }; 18 | 19 | export const ThemeContext = React.createContext(); 20 | 21 | export const ThemeProvider = ({ initialTheme, children }) => { 22 | const [theme, setTheme] = React.useState(getInitialTheme); 23 | 24 | const rawSetTheme = (rawTheme) => { 25 | const root = window.document.documentElement; 26 | const isDark = rawTheme === 'dark'; 27 | 28 | root.classList.remove(isDark ? 'light' : 'dark'); 29 | root.classList.add(rawTheme); 30 | 31 | localStorage.setItem('color-theme', rawTheme); 32 | }; 33 | 34 | if (initialTheme) { 35 | rawSetTheme(initialTheme); 36 | } 37 | 38 | React.useEffect(() => { 39 | rawSetTheme(theme); 40 | }, [theme]); 41 | 42 | return ( 43 | 44 | {children} 45 | 46 | ); 47 | }; -------------------------------------------------------------------------------- /src/pages/Home/Contact/Contact.js: -------------------------------------------------------------------------------- 1 | //Contact 2 | import React from "react"; 3 | import appointment from "../../../assets/images/appointment.png"; 4 | import CustomButton from "../../Shared/CustomButton/CustomButton"; 5 | 6 | const Contact = () => { 7 | return ( 8 |
15 |
16 |

17 | Contact us 18 |

19 |

20 | Stay connected with us 21 |

22 |
23 | 28 |
29 | 34 |
35 | 40 |
41 |
42 | Submit 43 |
44 |
45 |
46 |
47 | ); 48 | }; 49 | 50 | export default Contact; 51 | -------------------------------------------------------------------------------- /src/pages/Home/Testimonials/Testimonials.js: -------------------------------------------------------------------------------- 1 | // Testimonial 2 | import React from "react"; 3 | import quote from "../../../assets/icons/quote.svg"; 4 | import people1 from "../../../assets/images/people1.png"; 5 | import people2 from "../../../assets/images/people2.png"; 6 | import people3 from "../../../assets/images/people3.png"; 7 | import Review from "../Review/Review"; 8 | 9 | const Testimonials = () => { 10 | const reviews = [ 11 | { 12 | _id: 1, 13 | name: "Winson Harry", 14 | review: "", 15 | location:'California', 16 | img: people1, 17 | }, 18 | { 19 | _id: 2, 20 | name: "Winson Harry", 21 | review: "", 22 | location:'California', 23 | img: people2, 24 | }, 25 | { 26 | _id: 3, 27 | name: "Winson Harry", 28 | review: "", 29 | location:'California', 30 | img: people3, 31 | }, 32 | ]; 33 | 34 | return ( 35 |
36 |
37 |
38 |

Testimonials

39 |

What our patients say

40 |
41 |
42 | 43 |
44 |
45 |
46 | {reviews.map((review) => ( 47 | 48 | ))} 49 |
50 |
51 | ); 52 | }; 53 | 54 | export default Testimonials; 55 | -------------------------------------------------------------------------------- /src/pages/Dashboard/Users/Users.js: -------------------------------------------------------------------------------- 1 | // User 2 | import React, { useEffect, useState } from "react"; 3 | import { useQuery } from "react-query"; 4 | import Loading from "../../Shared/Loading/Loading"; 5 | import UsersRow from "./../Dashboard/UsersRow/UsersRow"; 6 | 7 | const Users = () => { 8 | const { 9 | data: users, 10 | isLoading, 11 | refetch, 12 | } = useQuery(["users"], () => 13 | fetch("http://localhost:5000/user", { 14 | method:"GET", 15 | headers:{ 16 | authorization:`Bearer ${localStorage.getItem("accessToken")}` 17 | } 18 | }).then((res) => res.json()) 19 | ); 20 | 21 | if (isLoading) { 22 | return ; 23 | } 24 | return ( 25 |
26 |

27 | All Users: {users?.length} 28 |

29 |
30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | {users?.map((user, index) => ( 42 | 48 | ))} 49 | 50 |
NameDateTime
51 |
52 |
53 |
54 | ); 55 | }; 56 | 57 | export default Users; 58 | -------------------------------------------------------------------------------- /src/pages/Appointment/AvailableAppointments/AvailableAppointments.js: -------------------------------------------------------------------------------- 1 | // Available Appoinment 2 | import { format } from "date-fns"; 3 | import React, { useState } from "react"; 4 | import { useEffect } from "react"; 5 | import { useQuery } from "react-query"; 6 | import Loading from "../../Shared/Loading/Loading"; 7 | import BookingModal from "../BookingModal/BookingModal"; 8 | import Service from "../Service/Service"; 9 | 10 | const AvailableAppointments = ({ date }) => { 11 | // const [services, setServices] = useState([]); 12 | const [treatment, setTreatment] = useState(null); 13 | 14 | const formattedDate = format(date, "PP"); 15 | 16 | const { data: services, isLoading, refetch } = useQuery(["available", formattedDate], () => 17 | fetch(`http://localhost:5000/available?date=${formattedDate}`).then((res) => 18 | res.json() 19 | ) 20 | ); 21 | 22 | if (isLoading) { 23 | return 24 | } 25 | 26 | // useEffect(() => { 27 | // fetch(`http://localhost:5000/available?date=${formattedDate}`) 28 | // .then((res) => res.json()) 29 | // .then((data) => { 30 | // setServices(data); 31 | // }); 32 | // }, [formattedDate]); 33 | 34 | return ( 35 |
36 |

37 | Available appointment on {format(date, "PP")} 38 |

39 |
40 | {services?.map((service) => ( 41 | 46 | ))} 47 |
48 | {treatment && ( 49 | 55 | )} 56 |
57 | ); 58 | }; 59 | 60 | export default AvailableAppointments; 61 | -------------------------------------------------------------------------------- /src/pages/Dashboard/MyAppointments/MyAppointments.js: -------------------------------------------------------------------------------- 1 | // My Appoinment 2 | import React from "react"; 3 | import { useEffect } from "react"; 4 | import { useState } from "react"; 5 | import { useAuthState } from "react-firebase-hooks/auth"; 6 | import auth from "./../../../firebase/Firebase.init"; 7 | import { useNavigate } from 'react-router-dom'; 8 | import { signOut } from 'firebase/auth'; 9 | 10 | const MyAppointments = () => { 11 | const [appointments, setAppointments] = useState([]); 12 | const [user] = useAuthState(auth); 13 | const navigate = useNavigate(); 14 | 15 | useEffect(() => { 16 | fetch(`http://localhost:5000/booking?patient=${user?.email}`, { 17 | method: "GET", 18 | headers: { 19 | authorization: `Bearer ${localStorage.getItem("accessToken")}`, 20 | }, 21 | }) 22 | .then((res) => { 23 | if (res.status === 401 || res.status===403) { 24 | navigate('/') 25 | signOut(auth); 26 | localStorage.removeItem('accessToken'); 27 | } 28 | return res.json() 29 | }) 30 | .then((data) => { 31 | setAppointments(data); 32 | }); 33 | }, []); 34 | 35 | return ( 36 |
37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | {appointments?.map((a, index) => ( 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ))} 58 | 59 |
NameDateTimeTreatment
{index + 1}{a.patientName}{a.date}{a.slot}{a.treatment}
60 |
61 |
62 | ); 63 | }; 64 | 65 | export default MyAppointments; 66 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 19 | 20 | 29 | React App 30 | 31 | 32 | 33 |
34 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/pages/About/About.js: -------------------------------------------------------------------------------- 1 | // About 2 | import React from "react"; 3 | import SubhamHr from "./../../assets/images/shubham.jpg"; 4 | import {Link} from 'react-router-dom'; 5 | import AOS from "aos"; 6 | import "aos/dist/aos.css"; 7 | AOS.init(); 8 | 9 | const About = () => { 10 | 11 | return ( 12 |
13 |
14 |
19 |

20 | Vice President Information Technology at Readymotive 21 |

22 |

23 | World's cheapest IOT fuel telematic platform can help vehicle owners 24 | solve almost every fuel related issue be it fuel theft, wastage, 25 | leakages, inefficiency etc. and also displays real time tracking. 26 |

27 |
28 | 33 | 36 |
37 |
38 |
39 | hero 48 |
49 |
50 |
51 | ); 52 | }; 53 | 54 | export default About; 55 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | // App js 2 | import "./App.css"; 3 | import Navbar from "./pages/Shared/Navbar/Navbar"; 4 | import { Routes, Route, Link } from "react-router-dom"; 5 | import Home from "./pages/Home/Home/Home"; 6 | import About from "./pages/About/About"; 7 | import Login from "./pages/Login/Login"; 8 | import Signup from "./pages/Signup/Signup"; 9 | import RequireAuth from "./pages/Login/RequireAuth"; 10 | import { ThemeProvider } from "./ThemeContext/ThemeContext"; 11 | import Background from "./pages/Shared/Theme/Background/Background"; 12 | import Appointment from "./pages/Appointment/Appointment/Appointment"; 13 | import { ToastContainer, toast } from "react-toastify"; 14 | import "react-toastify/dist/ReactToastify.css"; 15 | import Dashboard from "./pages/Dashboard/Dashboard/Dashboard"; 16 | import MyAppointments from "./pages/Dashboard/MyAppointments/MyAppointments"; 17 | import MyReview from './pages/Dashboard/MyReview/MyReview'; 18 | import Users from "./pages/Dashboard/Users/Users"; 19 | import RequireAdmin from "./pages/Login/RequireAdmin"; 20 | 21 | // function item 22 | function App() { 23 | return ( 24 |
25 | 26 | 27 |
28 | 29 | 30 | } /> 31 | 35 | 36 | 37 | } 38 | /> 39 | 43 | 44 | 45 | } 46 | /> 47 | 51 | 52 | 53 | } 54 | > 55 | }> 56 | }> 57 | }> 58 | 59 | 60 | } /> 61 | } /> 62 | 63 |
64 |
65 |
66 | 67 |
68 | ); 69 | } 70 | 71 | export default App; 72 | 73 | // apps 74 | -------------------------------------------------------------------------------- /src/pages/Shared/Navbar/Navbar.js: -------------------------------------------------------------------------------- 1 | // Navbar 2 | import { signOut } from "firebase/auth"; 3 | import React from "react"; 4 | import { useAuthState } from "react-firebase-hooks/auth"; 5 | import { Link } from "react-router-dom"; 6 | import auth from "../../../firebase/Firebase.init"; 7 | import Toggle from "../Theme/ThemeToggle/ThemeToggle"; 8 | 9 | const Navbar = () => { 10 | const [user, loading, error] = useAuthState(auth); 11 | 12 | const logOut = () => { 13 | signOut(auth); 14 | localStorage.removeItem('accessToken'); 15 | }; 16 | // menu item 17 | const menuItem = ( 18 | <> 19 |
  • 20 | Home 21 |
  • 22 | 23 |
  • 24 | About 25 |
  • 26 |
  • 27 | Appointment 28 |
  • 29 | { 30 | user &&
  • 31 | Dashboard 32 |
  • 33 | } 34 |
  • 35 | 36 |
  • 37 |
  • 38 | {user?.email ? ( 39 | 42 | ) : ( 43 | Login 44 | )} 45 |
  • 46 | 47 | ); 48 | 49 | return ( 50 |
    51 |
    52 |
    53 | 69 |
      73 | {menuItem} 74 |
    75 |
    76 | 77 | Doctors Hub 78 | 79 |
    80 |
    81 |
      {menuItem}
    82 |
    83 |
    84 | 100 |
    101 |
    102 | ); 103 | }; 104 | 105 | export default Navbar; 106 | -------------------------------------------------------------------------------- /public/services.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": 1, 4 | "name": "Teeth Orthodontics", 5 | "slots": [ 6 | "08.00 AM - 08.30 AM", 7 | "08.30 AM - 09.00 AM", 8 | "09.00 AM - 9.30 AM", 9 | "09.30 AM - 10.00 AM", 10 | "10.00 AM - 10.30 AM", 11 | "10.30 AM - 11.00 AM", 12 | "11.00 AM - 11.30 AM", 13 | "11.30 AM - 12.00 AM", 14 | "1.00 PM - 1.30 PM", 15 | "1.30 PM - 2.00 PM", 16 | "2.00 PM - 2.30 PM", 17 | "2.30 PM - 3.00 PM", 18 | "3.00 PM - 3.30 PM", 19 | "3.30 PM - 4.00 PM", 20 | "4.00 PM - 4.30 PM", 21 | "4.30 PM - 5.00 PM" 22 | ] 23 | }, 24 | { 25 | "_id": 2, 26 | "name": "Cosmetic Dentistry", 27 | "slots": [ 28 | "08.00 AM - 08.30 AM", 29 | "08.30 AM - 09.00 AM", 30 | "09.00 AM - 9.30 AM", 31 | "09.30 AM - 10.00 AM", 32 | "10.00 AM - 10.30 AM", 33 | "10.30 AM - 11.00 AM", 34 | "11.00 AM - 11.30 AM", 35 | "11.30 AM - 12.00 AM", 36 | "1.00 PM - 1.30 PM", 37 | "1.30 PM - 2.00 PM", 38 | "2.00 PM - 2.30 PM", 39 | "2.30 PM - 3.00 PM", 40 | "3.00 PM - 3.30 PM", 41 | "3.30 PM - 4.00 PM", 42 | "4.00 PM - 4.30 PM", 43 | "4.30 PM - 5.00 PM" 44 | ] 45 | }, 46 | { 47 | "_id": 3, 48 | "name": "Teeth Cleaning", 49 | "slots": [ 50 | "08.00 AM - 08.30 AM", 51 | "08.30 AM - 09.00 AM", 52 | "09.00 AM - 9.30 AM", 53 | "09.30 AM - 10.00 AM", 54 | "10.00 AM - 10.30 AM", 55 | "10.30 AM - 11.00 AM", 56 | "11.00 AM - 11.30 AM", 57 | "11.30 AM - 12.00 AM", 58 | "1.00 PM - 1.30 PM", 59 | "1.30 PM - 2.00 PM", 60 | "2.00 PM - 2.30 PM", 61 | "2.30 PM - 3.00 PM", 62 | "3.00 PM - 3.30 PM", 63 | "3.30 PM - 4.00 PM", 64 | "4.00 PM - 4.30 PM", 65 | "4.30 PM - 5.00 PM" 66 | ] 67 | }, 68 | { 69 | "_id": 4, 70 | "name": "Cavity Protection", 71 | "slots": [ 72 | "08.00 AM - 08.30 AM", 73 | "08.30 AM - 09.00 AM", 74 | "09.00 AM - 9.30 AM", 75 | "09.30 AM - 10.00 AM", 76 | "10.00 AM - 10.30 AM", 77 | "10.30 AM - 11.00 AM", 78 | "11.00 AM - 11.30 AM", 79 | "11.30 AM - 12.00 AM", 80 | "1.00 PM - 1.30 PM", 81 | "1.30 PM - 2.00 PM", 82 | "2.00 PM - 2.30 PM", 83 | "2.30 PM - 3.00 PM", 84 | "3.00 PM - 3.30 PM", 85 | "3.30 PM - 4.00 PM", 86 | "4.00 PM - 4.30 PM", 87 | "4.30 PM - 5.00 PM" 88 | ] 89 | }, 90 | { 91 | "_id": 5, 92 | "name": "Pediatric Dental", 93 | "slots": [ 94 | "08.00 AM - 08.30 AM", 95 | "08.30 AM - 09.00 AM", 96 | "09.00 AM - 9.30 AM", 97 | "09.30 AM - 10.00 AM", 98 | "10.00 AM - 10.30 AM", 99 | "10.30 AM - 11.00 AM", 100 | "11.00 AM - 11.30 AM", 101 | "11.30 AM - 12.00 AM", 102 | "1.00 PM - 1.30 PM", 103 | "1.30 PM - 2.00 PM", 104 | "2.00 PM - 2.30 PM", 105 | "2.30 PM - 3.00 PM", 106 | "3.00 PM - 3.30 PM", 107 | "3.30 PM - 4.00 PM", 108 | "4.00 PM - 4.30 PM", 109 | "4.30 PM - 5.00 PM" 110 | ] 111 | }, 112 | { 113 | "_id": 6, 114 | "name": "Oral Surgery", 115 | "slots": [ 116 | "08.00 AM - 08.30 AM", 117 | "08.30 AM - 09.00 AM", 118 | "09.00 AM - 9.30 AM", 119 | "09.30 AM - 10.00 AM", 120 | "10.00 AM - 10.30 AM", 121 | "10.30 AM - 11.00 AM", 122 | "11.00 AM - 11.30 AM", 123 | "11.30 AM - 12.00 AM", 124 | "1.00 PM - 1.30 PM", 125 | "1.30 PM - 2.00 PM", 126 | "2.00 PM - 2.30 PM", 127 | "2.30 PM - 3.00 PM", 128 | "3.00 PM - 3.30 PM", 129 | "3.30 PM - 4.00 PM", 130 | "4.00 PM - 4.30 PM", 131 | "4.30 PM - 5.00 PM" 132 | ] 133 | } 134 | ] -------------------------------------------------------------------------------- /src/pages/Appointment/BookingModal/BookingModal.js: -------------------------------------------------------------------------------- 1 | // Booking Modal 2 | import { format } from "date-fns"; 3 | import React from "react"; 4 | import { useAuthState } from "react-firebase-hooks/auth"; 5 | import auth from "./../../../firebase/Firebase.init"; 6 | import { toast } from "react-toastify"; 7 | 8 | const BookingModal = ({ setTreatment, treatment,refetch, date }) => { 9 | const { _id, name, slots } = treatment; 10 | const [user, loading] = useAuthState(auth); 11 | const formattedDate = format(date, "PP"); 12 | 13 | const handleBooking = (event) => { 14 | event.preventDefault(); 15 | const slot = event.target.slot.value; 16 | const booking = { 17 | treatmentId: _id, 18 | treatment: name, 19 | date: formattedDate, 20 | slot: slot, 21 | patient: user?.email, 22 | patientName: user?.displayName, 23 | phone: event.target.phone.value, 24 | }; 25 | 26 | fetch("http://localhost:5000/booking", { 27 | method: "POST", 28 | headers: { 29 | "content-type": "application/json", 30 | }, 31 | body: JSON.stringify(booking), 32 | }) 33 | .then((res) => res.json()) 34 | .then((data) => { 35 | if (data.success) { 36 | toast.success(`Appointment is set, ${formattedDate} at ${slot}`); 37 | } else { 38 | toast.error( 39 | `You already an appointment, ${data?.booking?.date} at ${data?.booking?.slot}` 40 | ); 41 | } 42 | refetch(); 43 | // to close the modal 44 | setTreatment(null); 45 | }); 46 | }; 47 | 48 | return ( 49 |
    50 | 51 |
    52 |
    53 | 59 |

    60 | Booking for: {name} 61 |

    62 |
    66 | 72 | 82 | 90 | 98 | 104 | 109 |
    110 |
    111 |
    112 |
    113 | ); 114 | }; 115 | 116 | export default BookingModal; 117 | -------------------------------------------------------------------------------- /src/pages/Home/Features/Features.js: -------------------------------------------------------------------------------- 1 | // Features 2 | import React from "react"; 3 | 4 | const Features = () => { 5 | return ( 6 |
    7 |
    14 |
    15 |

    16 | Echo Base...I've got something! 17 |

    18 |

    19 | Not much, but it could be a life form. This is Rouge Two. this is 20 | Rouge Two. Captain Solo, so you copy? 21 |

    22 | 25 |
    26 |
    27 | {/* Feature Section */} 28 |
    29 |

    30 | Artoo! 31 |

    32 |
    33 |
    34 |

    Vortex

    35 |

    36 | Their primary target will be the power generators. Prepare to open 37 | the shield. Sir, Rebel ships are coming into our sector. Good. Our 38 | first catch of the day. Stand by, ion control....Fire! The first 39 | transport is away. 40 |

    41 |
    42 |
    43 | Vortex 48 |
    49 |
    50 |
    51 |
    52 | use the force 57 |
    58 |
    59 |

    60 | Use the Force! 61 |

    62 |

    63 | We'll never get it out now. So certain are you. Always with you it 64 | cannot be done. Hear you nothing that I say? Master, moving stones 65 | around is one thing. This is totally different. No! No different! 66 |

    67 |
    68 |
    69 |
    70 |
    71 |

    72 | Life creates it 73 |

    74 |

    75 | There is no try. I can't. It's too big. Size matters not. Look at 76 | me. Judge me by my size, do you? Hm? Mmmm. And well you should 77 | not. For my ally in the Force. And a powerful ally it is. 78 |

    79 |
    80 |
    81 | Syncing 86 |
    87 |
    88 |
    89 |
    90 | ); 91 | }; 92 | 93 | export default Features; 94 | -------------------------------------------------------------------------------- /src/pages/Shared/Footer/Footer.js: -------------------------------------------------------------------------------- 1 | // Footer 2 | import React from "react"; 3 | import footer from "../../../assets/images/footer.png"; 4 | 5 | const Footer = () => { 6 | const year = new Date().getFullYear(); 7 | 8 | return ( 9 | 136 | ); 137 | }; 138 | 139 | export default Footer; 140 | -------------------------------------------------------------------------------- /src/pages/Login/Login.js: -------------------------------------------------------------------------------- 1 | // Login 2 | import React, { useEffect } from "react"; 3 | import { useState } from "react"; 4 | import { 5 | useSignInWithGoogle, 6 | useSignInWithEmailAndPassword, 7 | } from "react-firebase-hooks/auth"; 8 | import auth from "../../firebase/Firebase.init"; 9 | import { useForm } from "react-hook-form"; 10 | import Loading from "../Shared/Loading/Loading"; 11 | import { Link, useNavigate, useLocation } from "react-router-dom"; 12 | import useToken from './../../hooks/useToken'; 13 | 14 | const Login = () => { 15 | const [signInWithGoogle, googleUser, googleLoading, googleError] = 16 | useSignInWithGoogle(auth); 17 | const [signInWithEmailAndPassword, emailUser, emailLoading, emailError] = 18 | useSignInWithEmailAndPassword(auth); 19 | 20 | const [isPasswordShown, setIsPasswordShown] = useState(false); 21 | // toggle 22 | const togglePasswordVisibility = () => { 23 | if (!isPasswordShown) { 24 | setIsPasswordShown(true); 25 | return; 26 | } 27 | setIsPasswordShown(false); 28 | }; 29 | 30 | const { 31 | register, 32 | formState: { errors }, 33 | handleSubmit, 34 | } = useForm(); 35 | // on submit 36 | const onSubmit = (data) => { 37 | console.log(data); 38 | signInWithEmailAndPassword(data.email, data.password); 39 | }; 40 | 41 | const location = useLocation(); 42 | const navigate = useNavigate(); 43 | const redirect_uri = location?.state?.from || "/"; 44 | 45 | const [token] = useToken(googleUser || emailUser) 46 | 47 | 48 | useEffect(() => { 49 | if (token) { 50 | navigate(redirect_uri, { replace: true }); 51 | } 52 | },[token, redirect_uri, navigate]) 53 | 54 | // useEffect(() => { 55 | // if (googleUser || emailUser) { 56 | // navigate(redirect_uri, { replace: true }); 57 | // } 58 | // },[googleUser,emailUser,redirect_uri,navigate]) 59 | 60 | 61 | let signInError; 62 | if (googleError || emailError) { 63 | signInError = ( 64 |

    65 | {googleError?.message || emailError.message} 66 |

    67 | ); 68 | } 69 | 70 | if (googleLoading || emailLoading) { 71 | return ; 72 | } 73 | 74 | return ( 75 |
    76 |
    77 |
    78 |

    Login

    79 |
    80 |
    81 | 84 | 99 | 111 |
    112 |
    113 | 116 | 131 | 143 | 151 |
    152 | 153 | {signInError} 154 | 159 |
    160 |

    161 | 162 | New to This Site?{" "} 163 | 164 | Create A New Account 165 | 166 | 167 |

    168 |
    OR
    169 | 175 |
    176 |
    177 |
    178 | ); 179 | }; 180 | 181 | export default Login; 182 | -------------------------------------------------------------------------------- /src/pages/Signup/Signup.js: -------------------------------------------------------------------------------- 1 | // Sign Up 2 | import React from "react"; 3 | import { 4 | useSignInWithGoogle, 5 | useCreateUserWithEmailAndPassword, 6 | useUpdateProfile, 7 | } from "react-firebase-hooks/auth"; 8 | import auth from "../../firebase/Firebase.init"; 9 | import { useForm } from "react-hook-form"; 10 | import Loading from "../Shared/Loading/Loading"; 11 | import { Link, useLocation, useNavigate } from "react-router-dom"; 12 | import { useState } from "react"; 13 | import useToken from './../../hooks/useToken'; 14 | 15 | const Signup = () => { 16 | const [signInWithGoogle, googleUser, googleLoading, googleError] = 17 | useSignInWithGoogle(auth); 18 | 19 | const [createUserWithEmailAndPassword, emailUser, emailLoading, emailError] = 20 | useCreateUserWithEmailAndPassword(auth); 21 | 22 | const [updateProfile, updating, updateError] = useUpdateProfile(auth); 23 | 24 | const [token] = useToken(googleUser || emailUser); 25 | 26 | const location = useLocation(); 27 | const navigate = useNavigate(); 28 | const redirect_uri = location?.state?.from || "/"; 29 | const [isPasswordShown, setIsPasswordShown] = useState(false); 30 | 31 | const togglePasswordVisibility = () => { 32 | if (!isPasswordShown) { 33 | setIsPasswordShown(true); 34 | return; 35 | } 36 | setIsPasswordShown(false); 37 | }; 38 | 39 | const { 40 | register, 41 | formState: { errors }, 42 | handleSubmit, 43 | } = useForm(); 44 | 45 | const onSubmit = async (data) => { 46 | console.log(data); 47 | await createUserWithEmailAndPassword(data.email, data.password); 48 | await updateProfile({ displayName: data.Name }); 49 | // navigate(redirect_uri, { replace: true }); 50 | }; 51 | 52 | let signInError; 53 | if (googleError || emailError || updateError) { 54 | signInError = ( 55 |

    56 | 57 | {googleError?.message || emailError.message || updateError.message} 58 | 59 |

    60 | ); 61 | } 62 | 63 | if (googleLoading || emailLoading || updating) { 64 | return ; 65 | } 66 | 67 | if (token) { 68 | navigate('/appointment') 69 | } 70 | 71 | // if (googleUser || emailUser) { 72 | // navigate('/appointment') 73 | // navigate(redirect_uri, { replace: true }); 74 | // } 75 | 76 | return ( 77 |
    78 |
    79 |
    80 |

    Sign Up

    81 |
    82 |
    83 | 86 | 97 | 104 |
    105 |
    106 | 109 | 124 | 136 |
    137 |
    138 | 141 | 156 | 168 | 176 |
    177 | 178 | {signInError} 179 | 184 |
    185 |

    186 | 187 | Already Have An Account?{" "} 188 | 189 | Please Login 190 | 191 | 192 |

    193 |
    OR
    194 | 200 |
    201 |
    202 |
    203 | ); 204 | }; 205 | 206 | export default Signup; 207 | --------------------------------------------------------------------------------