├── 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 |
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 |
7 | {children}
8 |
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 |
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 |
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 |
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 |
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 | setTreatment(service)}
23 | disabled={slots.length === 0}
24 | htmlFor="booking-modal"
25 | className="btn btn-sm btn-secondary text-white uppercase bg-gradient-to-r from-secondary to-primary"
26 | >
27 | Book appointment
28 |
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' && Make Admin }
33 | Remove Admin
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 |
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 |
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 | Name
36 | Date
37 | Time
38 |
39 |
40 |
41 | {users?.map((user, index) => (
42 |
48 | ))}
49 |
50 |
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 | Name
43 | Date
44 | Time
45 | Treatment
46 |
47 |
48 |
49 | {appointments?.map((a, index) => (
50 |
51 | {index + 1}
52 | {a.patientName}
53 | {a.date}
54 | {a.slot}
55 | {a.treatment}
56 |
57 | ))}
58 |
59 |
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 | You need to enable JavaScript to run this app.
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 |
31 | Go Forward
32 |
33 |
34 | Go back
35 |
36 |
37 |
38 |
39 |
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 |
40 | Sign Out
41 |
42 | ) : (
43 | Login
44 | )}
45 |
46 | >
47 | );
48 |
49 | return (
50 |
51 |
52 |
53 |
54 |
61 |
67 |
68 |
69 |
75 |
76 |
77 | Doctors Hub
78 |
79 |
80 |
83 |
84 |
85 |
92 |
98 |
99 |
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 |
57 | ✕
58 |
59 |
60 | Booking for: {name}
61 |
62 |
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 |
23 | Commander Skywalker, do you copy?
24 |
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 |
48 |
49 |
50 |
51 |
52 |
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 |
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 |
16 |
17 |
18 |
47 |
68 |
97 |
98 |
Through the Force
99 |
125 |
126 |
127 |
134 |
135 |
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 |
160 |
161 |
162 | New to This Site?{" "}
163 |
164 | Create A New Account
165 |
166 |
167 |
168 |
OR
169 |
signInWithGoogle()}
171 | className="btn btn-outline"
172 | >
173 | Continue with google
174 |
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 |
185 |
186 |
187 | Already Have An Account?{" "}
188 |
189 | Please Login
190 |
191 |
192 |
193 |
OR
194 |
signInWithGoogle()}
196 | className="btn btn-outline"
197 | >
198 | Continue with google
199 |
200 |
201 |
202 |
203 | );
204 | };
205 |
206 | export default Signup;
207 |
--------------------------------------------------------------------------------