Code Monkey home page Code Monkey logo

copilot-and-sons-pharmacy's Introduction

Typing SVG

Copilot & Sons: El7a2ny Pharmacy

Table of Contents

  1. ๐Ÿš€ Motivation
  2. ๐Ÿงฑ Build Status
  3. ๐ŸŽจ Code Style
  4. โš’๏ธ Tech and Framework used
  5. ๐Ÿ”ฅ Features & Screenshots
  6. ๐Ÿ’ป Code Examples
  7. ๐Ÿช› Installation
  8. ๐Ÿ“š API Reference
  9. ๐Ÿงช Tests
  10. ๐Ÿง‘๐Ÿปโ€๐Ÿซ How to Use
  11. ๐Ÿค Contribute
  12. ๐Ÿซก Credits
  13. ๐Ÿ“œ License

๐Ÿš€ Motivation

Welcome to Copilot & Sons El7a2ny Pharmacy, a state-of-the-art integrated pharmacy management software. This project is motivated by the desire to streamline and automate pharmacy operations, providing a seamless experience for pharmacists and patients within the healthcare ecosystem.

๐Ÿงฑ Build Status

example workflow example workflow

  • This project is under development and should not be used in a production settings
  • Check Issues for a list of all the reported issues
  • More automated tests should be added in the future
  • More documentation should be added

๐ŸŽจ Code Style

We use Prettier and ESLint to enforce a consistent code style. We use an edited version of the default ESLint TypeScript config. You can check the config in the .eslintrc.js file.

Useful Commands

Useful Commands

  • Check formatting using Prettier
npm run format
  • And then fix formatting using Prettier
npm run format:fix
  • Check linting using ESLint
npm run lint
  • And then fix linting using ESLint
npm run lint:fix
  • Check compilation of all subpackages using TypeScript
npm run compile:all

โš’๏ธ Tech and Framework used

๐Ÿ”ฅ Features & Screenshots

๐Ÿ‘ค User Registration
  • Register as a patient.
  • Submit a request to register as a pharmacist.
  • Upload documents to register as pharmacist

image

๐Ÿ” User Authentication
  • Patient/Pharmacist/Administrator: Login with username and password.
  • Patient/Pharmacist/Administrator: Logout.

image

๐Ÿ”ง Administrator Operations
  • Adminstrator: Add another administrator with a set username and password.

  • Adminstrator: Remove a pharmacist/patient from the system.

  • Adminstrator: View all information uploaded by a pharmacist to apply to join the platform.

  • Adminstrator: Accept or reject the request of a pharmacist to join the platform.

    image

๐Ÿ’Š Pharmacist Operations
  • Pharmacist: Upload and submit required documents upon registration such as ID, pharmacy degree, and working licenses.
  • Pharmacist: View the available quantity and sales of each medicine.
  • Pharmacist: Search for medicine based on name.
  • Pharmacist: Filter medicines based on medicinal use.
  • Pharmacist: Add a medicine with its details (active ingredients), price, and available quantity.
  • Pharmacist: Upload medicine image.
  • Pharmacist: Edit medicine details and price.
  • Pharmacist: Archive/unarchive a medicine.
  • Adminstrator/Pharmacist: View a total sales report based on a chosen month.
  • Pharmacist: Filter sales report based on a medicine/date.
  • Pharmacist: Chat with a doctor.
  • Pharmacist: Receive a notification once a medicine is out of stock on the system and via email.

image

๐Ÿ” User Account Management
  • Patient/Pharmacist/Administrator: Change my password.

  • Patient/Pharmacist/Administrator: Reset a forgotten password through OTP sent to email.

    image

๐Ÿ’Š๐Ÿ›’ Medicine and Order Management
  • Patient/Pharmacist/Administrator: View a list of all available medicines (including a picture of medicine, price, description).

  • Patient: Add an over-the-counter medicine to my cart.

  • Patient: Add a prescription medicine to my cart based on my prescription.

  • Patient: View cart items.

  • Patient: Remove an item from the cart.

  • Patient: Change the amount of an item in the cart.

  • Patient: Checkout my order.

  • Patient: Add a new delivery address (or multiple addresses).

  • Patient: Choose a delivery address from the available addresses.

  • Patient: Choose to pay with a wallet, credit card (using Stripe), or cash on delivery.

  • Patient: View current and past orders.

  • Patient: View order details and status.

  • Patient: Cancel an order.

  • Patient: View alternatives to a medicine that is out of stock based on the main active ingredient.

  • Patient: Chat with a pharmacist.

  • Pharmacist: View the amount in my wallet.

    image

๐Ÿ’ป Code Examples

BE Routes
app.use('/api/medicine', medicinesRoute)
app.use('/api/patient', patientsRoute)
app.use('/api/admin', adminsRoute)
app.use('/api/pharmacist', pharmacistRoute)
app.use('/api/cart', cartsRoute)
app.use('/api/debug', debugRouter)
app.use('/api', authRouter)
app.use('/api', deliveryAddressRouter)
app.use('/api/order', orderRouter)
app.use('/api', chatsRouter)
app.use('/api', notificationRouter)
app.use('/api', chatsRouter)
BE Cart Controller
export const addToCart = asyncWrapper(async (req: Request, res: Response) => {
  const cart = await addToCartService(req.body, req.username)
  res.json({ success: SUCCESS, data: cart })
})

export const viewCart = asyncWrapper(async (req: Request, res: Response) => {
  const cartItems = await viewCartService(req.username)
  res.json({ success: SUCCESS, data: cartItems })
})

export const removeItemFromCart = asyncWrapper(
  async (req: Request, res: Response) => {
    const cart = await removeItemFromCartService(
      req.query.medicineId,
      req.username
    )
    res.json({ success: SUCCESS, data: cart })
  }
)

export const ClearAllItemsFromCart = asyncWrapper(
  async (req: Request, res: Response) => {
    const cart = await ClearCartService(req.username)
    res.json({ success: SUCCESS, data: cart })
  }
)

export const changeCartItemQuantity = asyncWrapper(
  async (req: Request, res: Response) => {
    const cart = await changeCartItemQuantityService(req.body, req.username)
    res.json({ success: SUCCESS, data: cart })
  }
)

export const addPrescriptiontoCart = asyncWrapper(
  async (req: Request, res: Response) => {
    const cart = await addPrescriptiontoCartService(
      req.body.prescriptionId,
      req.username
    )
    res.json({ success: SUCCESS, data: cart })
  }
)
BE Clear Cart Service
export async function ClearCartService(username: any) {
  const patientUser = await userModel.findOne({ username })
  const user = await Patient.findOne({ user: patientUser?._id })

  const cart = await CartModel.findOne({ _id: user?.cart })

  if (!cart) {
    return null
  }

  cart.items.forEach(async (cartItem) => {
    if (cartItem.byPrescription !== null) {
      await PrescriptionModel.updateOne(
        { _id: cartItem.byPrescription },
        { $set: { isFilled: false } }
      )
    }
  })

  cart.items = []
  const updatedCart = await cart.save()

  return updatedCart
}
BE Cart Model
interface ICartItem {
  medicine: IMedicine
  quantity: number
  byPrescription: PrescriptionDocument | null
}

const cartItemSchema = new Schema<ICartItem>({
  medicine: { type: Schema.Types.ObjectId, ref: 'Medicine' },
  quantity: Number,
  byPrescription: {
    type: Schema.Types.ObjectId,
    ref: 'Prescription',
    default: null,
  },
})

export interface ICart extends Document {
  items: Array<{
    medicine: IMedicine
    quantity: number
    byPrescription: PrescriptionDocument | null
  }>
}

const cartSchema = new Schema<ICart>({
  items: [cartItemSchema],
})

export const CartModel: Model<ICart> = model('Cart', cartSchema)
BE Admin Validator
const adminValidator = Joi.object({
  username: Joi.string().alphanum().min(3).max(30).required().messages({
    'string.base': 'Username should be a string',
    'string.alphanum': 'Username should only contain alphanumeric characters',
    'string.min': 'Username should have a minimum length of {#limit}',
    'string.max': 'Username should have a maximum length of {#limit}',
    'any.required': 'Username is required',
  }),

  email: Joi.string().email().required().messages({
    'string.email': 'Invalid email address',
    'any.required': 'Email is required',
  }),

  password: Joi.string()
    .min(8)
    .required()
    .custom((value) => {
      if (!isStrongPassword(value)) {
        const errorReason = getPasswordStrengthReason(value)
        throw new AppError(errorReason, 400, ERROR) // Throw a custom error message
      }

      return value
    })
    .messages({
      'string.min': 'Password should have a minimum length of {#limit}',
      'any.required': 'Password is required',
    }),
})
FE Admin Routes
export const adminDashboardRoutes: RouteObject[] = [
  {
    element: <AdminDashboardLayout />,
    children: [
      {
        path: '',
        element: <AdminDashboardHome />,
      },
      {
        path: 'change-password',
        element: <ChangePassword />,
      },
      {
        path: 'add-admin',
        element: <AddingAdmin />,
      },
      {
        path: 'remove-user',
        element: <RemoveUser />,
      },
      {
        path: 'get-approved-pharmacists',
        element: <GetApprovedPharmacists />,
      },
      {
        path: 'get-pending-pharmacists',
        element: <GetPharmacists />,
      },
      {
        path: 'medicines',
        children: [
          {
            path: '',
            element: <ViewAllMedicines />,
          },
          {
            path: 'search-for-medicine',
            element: <SearchForMedicine />,
          },
          {
            path: 'allUses',
            element: <MedicinalUses />,
          },
          {
            path: 'allUses/:name',
            element: <FilteredMedicines />,
          },
        ],
      },
      {
        path: 'viewPatients',
        element: <ViewPatients />,
      },
      {
        path: 'viewPatients/info/:id',
        element: <PatientInfo />,
      },
      {
        path: 'sales-and-quantity',
        element: <ViewMedicineSalesAndQuantity />,
      },
      {
        path: 'clinic',
        element: <RedirectToClinic />,
      },
    ],
  },
]
FE Login Page
export const Login = () => {
  const { refreshUser } = useAuth()

  return (
    <>
      <ApiForm<LoginRequest>
        fields={[
          { label: 'Username', property: 'username' },
          { label: 'Password', property: 'password' },
        ]}
        validator={LoginRequestValidator}
        successMessage="Logged in successfully."
        action={login}
        onSuccess={() => refreshUser()}
        buttonText="Login"
      />
      <Link to={'/forgot-password'}>forgot your password?</Link>
      <br />
      <Link to={'../register-request'}>SIGN UP</Link>
    </>
  )
}

๐Ÿช› Installation

  • Make sure you have Node and Git installed

  • Make a new folder for the sub system of Clinic & Pharmacy

mkdir Copilot-and-Sons
cd Copilot-and-Sons
  • Clone this repo + pharmacy repo
git clone https://github.com/advanced-computer-lab-2023/Copilot-and-Sons-Clinic
git clone https://github.com/advanced-computer-lab-2023/Copilot-and-Sons-Pharmacy
  • Install dependencies for clinic
cd Copilot-and-Sons-Clinic
npm install
  • Install dependencies for pharmacy
cd ../Copilot-and-Sons-Pharmacy
npm install

๐Ÿ“š API Reference

Note

  • All responses are wrapped in { status: 'success' | 'error', data: <The response data> }
  • All endpoints are prefixed by /api/<The URI>
Admin Endpoints
  • POST /admin/add-admin - Add a new admin
    • Request Body
      {
          username: string
          password: string
          email: string
      }
      
    • Response Body:
      user: {
          username: string
          password: string
          email: string
      }
      
  • DELETE /admin/removeUser - Delete a user by username
    • Request Body
          {
              data: {
                  username: string
              }
          }
      
    • Response Body: N/A
  • GET /admin/getPendingPharmacists - Get pending pharmacists
    • Request Body: N/A
    • Response Body:
      {
          user: {
              username: string
              password: string
              type: UserType
          },
          name: string,
          email: string,
          dateOfBirth: Date,
          hourlyRate: number,
          affilation: string,
          status: 'Accepted' | 'Pending' | 'Rejected',
          educationalBackground: {
              major: string,
              university: string,
              graduationYear: number,
              degree: 'Associate degree' | "Bachelor's degree" | Master's degree", |'Doctoral degree',,
          },
          documents: [string],
          walletMoney: number,
      }
      
  • GET admin/getAcceptedPharmacists - Get accepted pharmacists
    • Request Body: N/A
    • Response Body:
      {
          user: {
              username: string
              password: string
              type: UserType
          },
          name: string,
          email: string,
          dateOfBirth: Date,
          hourlyRate: number,
          affilation: string,
          status: 'Accepted' | 'Pending' | 'Rejected',
          educationalBackground: {
              major: string,
              university: string,
              graduationYear: number,
              degree: 'Associate degree' | "Bachelor's degree" | Master's degree", |'Doctoral degree',,
          },
          documents: [string],
          walletMoney: number,
      }
      
Auth Endpoints
  • POST /patient/register - Register patient

    • Request Body
      {
          username: string
          name: string
          email: string
          password: string
          dateOfBirth: string | null
          gender: string
          mobileNumber: string
          emergencyContact: {
              fullName: string
              mobileNumber: string
              relation: string
          }
      }
      
    • Response Body:
      {
          token: string // The jwt token
      }
      
  • POST /auth/login - Authenticate a user and retrieve an access token.

    • Request Body:
    {
      "username": "string",
      "password": "string"
    }
    • Response Body:
    {
      "token": "string"
    }
  • GET /auth/me - Retrieve information about the currently authenticated user.

  • Response Body:

    {
      "id": "string",
      "username": "string",
      "name": "string",
      "email": "string",
      "dateOfBirth": "string",
      "gender": "string",
      "mobileNumber": "string",
      "emergencyContact": {
        "fullName": "string",
        "mobileNumber": "string"
      }
    }
  • POST /patient/requestOtp - Request to send OTP for forgetting password

    • Request Body:
    {
        email: string
    }
    
    • Response Body:: N/A
  • POST /patient/verifyOtp - Verify OTP for forgetting password

    • Request Body:
    {
        email: string,
        otp: string,
    }
    
    • Response Body:: N/A
  • POST /patient/updatePassword - Update patient password after forgetting password

    - **Request Body:**
    ```
    {
        email: string,
        newPassword: string
    }
    ```
    
    - **Response Body:**: N/A
    
Cart Endpoints
  • POST /cart/add - Add item to shopping cart

    • Request Body
      { medicineId: string, quantity: string }
      
    • Response Body:
      {
          items: [
              {
                  medicine: {
                      name: string,
                      price: string,
                      description: string,
                      quantity: number,
                      Image: string,
                      activeIngredients: [string],
                      medicinalUse: [string],
                      sales: number,
                      requiresPrescription: boolean,
                      status: string,
                      discountedPrice: number
                  },
                  quantity:  number,
                  byPrescription: boolean
              }
          ]
      }
      
  • GET /cart/view - View cart items for current user

    • Request Body: N/A
    • Response Body:
      {
          items: [
              {
                  medicine: {
                      name: string,
                      price: string,
                      description: string,
                      quantity: number,
                      Image: string,
                      activeIngredients: [string],
                      medicinalUse: [string],
                      sales: number,
                      requiresPrescription: boolean,
                      status: string,
                      discountedPrice: number
                  },
                  quantity:  number,
                  byPrescription: boolean
              }
          ]
      }
      
  • DELETE /cart/remove - Delete item from the cart

    • Request Body:
      { medicineId: string }
      
    • Response Body:
      {
          items: [
              {
                  medicine: {
                      name: string,
                      price: string,
                      description: string,
                      quantity: number,
                      Image: string,
                      activeIngredients: [string],
                      medicinalUse: [string],
                      sales: number,
                      requiresPrescription: boolean,
                      status: string,
                      discountedPrice: number
                  },
                  quantity:  number,
                  byPrescription: boolean
              }
          ]
      }
      
  • PUT /cart/change-quantity - Change quantity of item in cart

    • Request Body:
      { medicineId: string, quantity: number }
      
    • Response Body:
      {
          items: [
              {
                  medicine: {
                      name: string,
                      price: string,
                      description: string,
                      quantity: number,
                      Image: string,
                      activeIngredients: [string],
                      medicinalUse: [string],
                      sales: number,
                      requiresPrescription: boolean,
                      status: string,
                      discountedPrice: number
                  },
                  quantity:  number,
                  byPrescription: boolean
              }
          ]
      }
      
  • POST /cart/clear - Clear cart items

    • Request Body: N/A
    • Response Body: { items: [ { medicine: { name: string, price: string, description: string, quantity: number, Image: string, activeIngredients: [string], medicinalUse: [string], sales: number, requiresPrescription: boolean, status: string, discountedPrice: number }, quantity: number, byPrescription: boolean } ] }
Medicine Endpoints
  • GET /medicine - Get all medicines

    • Request Body: N/A
    • Response Body:
      [
        {
            name: string,
            price: string,
            description: string,
            quantity: number,
            Image: string,
            activeIngredients: [string],
            medicinalUse: [string],
            sales: number,
            requiresPrescription: boolean,
            status: string,
            discountedPrice: number
        }
      ]
      
  • GET /medicine/unarchivedMedicines - Get all unarchived medicines

    • Request Body: N/A
    • Response Body:
      [
        {
            name: string,
            price: string,
            description: string,
            quantity: number,
            Image: string,
            activeIngredients: [string],
            medicinalUse: [string],
            sales: number,
            requiresPrescription: boolean,
            status: string,
            discountedPrice: number
        }
      ]
      
  • PATCH /medicine/archiveMedicine/:name - Archive a medice by name

    • Request Body: N/A
    • Response Body: N/A
  • PATCH /medicine/unarchiveMedicine/:name - Unarchive a medice by name

    • Request Body: N/A
    • Response Body: N/A
  • GET /medicine/viewAlternatives/:id - Get all alternatives of a medicine by id

    • Request Body: N/A
    • Response Body:
      [
        {
            name: string,
            price: string,
            description: string,
            quantity: number,
            Image: string,
            activeIngredients: [string],
            medicinalUse: [string],
            sales: number,
            requiresPrescription: boolean,
            status: string,
            discountedPrice: number
        }
      ]
      
  • GET /medicine/quantity-sales/:id - Get quantity & sales of a medicine

    • Request Body: N/A
    • Response Body:
      {
          name: string,
          quantity: number,
          sales: number,
      }
      
  • GET /medicine/salesReportByMonth?month={month} - Get sales of a medicine by month

    • Request Body: N/A
    • Response Body:
      {
          name: string,
          sales: number,
      }
      
  • GET /medicine/salesReportByMonth?date={date} - Get sales of a medicine by date

    • Request Body: N/A
    • Response Body:
      {
          name: string,
          sales: number,
      }
      
  • POST /medicine/addMedicine - Add a new medicine

    • Request Body:
    {
      name: string,
      price: number,
      description: string,
      quantity: number,
      Image: File,
      mainActiveIngredient: string,
      activeIngredients: string,
      medicinalUse: string,
      sales: number,
      needPrescription: boolean,
    }
    
    • Response Body:
      {
          name: string,
          price: string,
          description: string,
          quantity: number,
          Image: string,
          activeIngredients: [string],
          medicinalUse: [string],
          sales: number,
          requiresPrescription: boolean,
          status: string,
      }
      
  • GET /admin/getMedicineByName/:name - Get a medicine by its name

    • Request Body: N/A
    • Response Body:
      [
        {
            name: string,
            price: string,
            description: string,
            quantity: number,
            Image: string,
            activeIngredients: [string],
            medicinalUse: [string],
            sales: number,
            requiresPrescription: boolean,
            status: string,
            discountedPrice: number
        }
      ]
      
  • GET /admin/getMedicineByName/:name - Get a medicine by its name

    • Request Body: N/A
    • Response Body:
      [
        {
            name: string,
            price: string,
            description: string,
            quantity: number,
            Image: string,
            activeIngredients: [string],
            medicinalUse: [string],
            sales: number,
            requiresPrescription: boolean,
            status: string,
            discountedPrice: number
        }
      ]
      
  • GET /medicine/allMedicinalUses - Get all use cases

    • Request Body: N/A
    • Response Body: [string]
  • GET /medicine/filterByMedicinalUse/:name - Get all medicine for a usecase

    • Request Body: N/A
    • Response Body:
      [
        {
            name: string,
            price: string,
            description: string,
            quantity: number,
            Image: string,
            activeIngredients: [string],
            medicinalUse: [string],
            sales: number,
            requiresPrescription: boolean,
            status: string,
            discountedPrice: number
        }
      ]
      
  • PUT /medicine/wallet/:totalMoney - Update patient wallet

    • Request Body: N/A
    • Response Body: number -> The new wallet amount
Chat Endpoints
  • `POST '/chats/get-all' - Get all chats for a user

    • Request Body:
    {
        'username': string // Could be username of a patient, doctor, or admin
    }
    
    • Response Body
    {
        'id': string
        'users': Array<{
            'id': string
            'username': string
            'name': string
            'email': string
            'type': UserType
        }>
        'createdAt': string
        'lastMessage': string
        'hasUnreadMessages': boolean
    }
    
  • POST /chats/create-or-get - Creates a new chat or gets one if it already exists between the users

    • Request Body
      {
          'initiator': string
          'receiver': string
      }
      
    • Reponse Body: string -> ID of the created chat
  • POST /chats/get-by-id - Gets a chat by its id

    • Request Body
      {
          'chatId': string
          'readerUsername': string
      }
      
    • Reponse Body
      {
          'id': string
          users: Array<{
              'id': string
              'username': string
              'name': string
              'email': string
              'type': UserType
          }>
          'messages': Array<{
              'id': string
              'sender': string
              'senderType': UserType
              'senderDetails': {
                  'name': string
                  'email': string
              }
              'content': string
              'createdAt': string
          }>
          'createdAt': string
          'lastMessage': string
          'hasUnreadMessages': boolean
      }
      
  • POST /chats/send-message - Sends a message

    • Request Body
      {
          'chatId': string
          'senderUsername': string
          'content': string
      }
      
    • Reponse Body: N/A
  • POST '/chats/mark-as-read' - Marks a chat as being read

    • Request Body
      {
          'chatId': string
          'username': string
      }
      
    • Reponse Body: N/A
Delivery Address Endpoints
  • `GET '/patients/:username/delivery-addresses' - Get all delivery addresses of a user by username

    • Request Body: N/A
    • Response Body
    [
      {
          _id: string
          address: string
          city: string
          country: string
      }
    ]
    
  • POST /patients/:username/delivery-addresses - Create a new delivery address for a user

    • Request Body
      {
          address: string,
          city: string,
          country: string,
      }
      
    • Reponse Body:
      [
          {
              _id: string
              address: string
              city: string
              country: string
          }
      ]
      
  • DELETE /patients/:patientUsername/delivery-addresses/:deliveryAddressId - Delete delivery address by id and username of patient

    • Request Body: N/A
    • Reponse Body: N/A
  • PUT /patients/:patientUsername/delivery-addresses/:deliveryAddressId - Update delivery address

    • Request Body
      {
          address: string,
          city: string,
          country: string,
      }
      
    • Reponse Body:
    [
        {
            _id: string
            address: string
            city: string
            country: string
        }
    ]
    
Notifications Endpoints
  • POST /notifications/all' - Get all notifications for a user

    • Request Body:
      {
          'username': string,
      }
      
    • Reponse Body:
      {
          notifications: [
              {
                  _id: string
                  title: string
                  description?: string
              }
          ]
      }
      
  • DELETE /notifications' - Delete a notification

    • Request Body:
    {
      username: string,
      notificationId: string,
    }
    
    • Reponse Body: N/A
Orders Endpoints
  • POST /order/addOrder' - Add an order

    • Request Body:

      {
        patientID: string,
        total: number,
        date: string,
        address: string,
        paymentMethod: 'wallet' | 'cash' | 'credit-card'
      }
      
    • Reponse Body:

      {
        patientID: string,
        total: number,
        date: Date,
        status: 'pending' | 'delivered' | 'cancelled'
        cartID: string,
        paymentMethod: string,
      
        address: {
          address: string,
          city: string,
          country: string,
        },
      }
      
  • GET /order/orders' - Get all orders of current patient

    • Request Body: N/A

    • Reponse Body:

      [
        {
          patientID: string,
          total: number,
          date: Date,
          status: 'pending' | 'delivered' | 'cancelled'
          cartID: string,
          paymentMethod: string,
      
          address: {
            address: string,
            city: string,
            country: string,
          },
        }
      ]
      
  • GET /order/viewOrder/${id} - Get details about order by id

    • Request Body: N/A

    • Reponse Body:

      {
        patientID: string,
        total: number,
        date: Date,
        status: 'pending' | 'delivered' | 'cancelled'
        cartID: string,
        paymentMethod: string,
      
        address: {
          address: string,
          city: string,
          country: string,
        },
      }
      
  • GET /order/cancelOrder/:id - Cancel order by id

    • Request Body: N/A
    • Reponse Body: N/A
Patient Endpoints
  • GET /patient/viewAllPatients' - View all patients

    • Request Body: N/A
    • Reponse Body:
      {
        user: string,
        name: string,
        email: string,
        mobileNumber: string,
        dateOfBirth: Date,
        gender: 'Male' | 'Female',
        emergencyContact: {
          fullName: string,
          mobileNumber: string,
          relation: string,
        },
        orders: [string],
        cart: string,
        deliveryAddresses: [
          {
            address: string,
            city: string,
            country: string,
          },
        ],
        walletMoney: number,
        familyMembers: [string],
        documents: [string],
        healthPackage: string,
        healthPackageRenewalDate: Date,
        notes: [string],
        healthRecords: [string],
        healthPackageHistory: [
          {
            healthPackage: string,
            date: Date,
          },
        ]
      }
      
  • POST /patient/requestOtp' - Request OTP to reset password

    • Request Body:
        {email: string}
      
    • Reponse Body: N/A
  • GET /admin/patientInfo/:id - Get info about patient by id

    • Request Body: N/A
    • Reponse Body:
      {
        user: string,
        name: string,
        email: string,
        mobileNumber: string,
        dateOfBirth: Date,
        gender: 'Male' | 'Female',
        emergencyContact: {
          fullName: string,
          mobileNumber: string,
          relation: string,
        },
        orders: [string],
        cart: string,
        deliveryAddresses: [
          {
            address: string,
            city: string,
            country: string,
          },
        ],
        walletMoney: number,
        familyMembers: [string],
        documents: [string],
        healthPackage: string,
        healthPackageRenewalDate: Date,
        notes: [string],
        healthRecords: [string],
        healthPackageHistory: [
          {
            healthPackage: string,
            date: Date,
          },
        ]
      }
      
  • POST /cart/addPrescriptiontoCart - Add prescription to cart

    • Request Body:
      { prescriptionId: string }
      
    • Reponse Body: N/A
Pharmacist Endpoints
  • GET /pharmacist/acceptPharmacistRequest/:id - Accept a pharmacist request by id

    • Request Body: N/A
    • Reponse Body: N/A
  • GET /pharmacist/rejectPharmacistRequest/:id - Reject a pharmacist request by id

    • Request Body: N/A
    • Reponse Body: N/A
  • GET /pharmacist/getPharmacist/:username - Get a pharmacist by username

    • Request Body: N/A
    • Reponse Body:
      {
          user: {
              username: string
              password: string
              type: UserType
          },
          name: string,
          email: string,
          dateOfBirth: Date,
          hourlyRate: number,
          affilation: string,
          status: 'Accepted' | 'Pending' | 'Rejected',
          educationalBackground: {
              major: string,
              university: string,
              graduationYear: number,
              degree: 'Associate degree' | "Bachelor's degree" | Master's degree", |'Doctoral degree',,
          },
          documents: [string],
          walletMoney: number,
      }
    
  • POST /pharmacist/addPharmacist - Request to register as a pharmacist

    • Request Body:
      {
        'name': string,
        'email': string,
        'username': string,
        'password': string,
        'dateOfBirth': Date,
        'hourlyRate': number,
        'affilation': string,
        'educationalBackground': {
          'major': string,
          'university': string,
          'graduationYear': string,
          'degree': string,
        }
        'status': string',
        'documents': File[],
      }
    
    • Reponse Body:
      {token: string} // The jwt token
    
  • PATCH /pharmacist/depositSalary/:id - Deposit a salary to the pharmacist by id

    • Request Body: N/A
    • Reponse Body: N/A

๐Ÿงช Tests

We use Postman to manually test all our api references by making sure the response is as expected. We use it as some kind of sanity-check.

Here is an example testing that logging in with an invalid username wouldn't pass authorization:

image

๐Ÿง‘๐Ÿปโ€๐Ÿซ How to Use

  • Make sure to follow the Installation steps first

  • Add a .env in the backend of both repos Copilot-and-Sons-Clinic and Copilot-and-Sons-Pharmacy with the following variables (replace the values with your own)

MONGO_URI="<Your Mongo Connection String>"
PORT=3000
BCRYPT_SALT="<A secret string to use for encrypting passwords>"
JWT_TOKEN="<A secret string to use for hashing JWT tokens>"
  • Start clinic
cd Copilot-and-Sons-Clinic
npm start
  • Start pharmacy in a different terminal
cd Copilot-and-Sons-Pharmacy
npm start

NOTE

If you want to use Docker Compose to start to project, you can replace the last step with docker compose up

๐Ÿค Contribute

We welcome contributions to Copilot&Sons El7a2ny Clinic. If you want to contribute, it's as easy as:

  1. Fork the repo
  2. Create a new branch (git checkout -b my-new-feature)
  3. Make changes
  4. Commit your changes (git commit -am 'Add some feature')
  5. Push to the branch (git push origin my-new-feature)
  6. Create a new Pull Request
  7. Wait for your PR to be reviewed and merged

NOTE

We welcome all contributions, but please make sure to follow our code style and linting rules. You can check the Code Style section for more details.

๐Ÿซก Credits

Docs

YouTube Videos

๐Ÿ“œ License

The software is open source under the Apache 2.0 License.

Apache 2.0

copilot-and-sons-pharmacy's People

Contributors

mathewhany avatar youssof-kandil avatar zahra-saadawy avatar youssef1shawky avatar dareenfadel avatar nairuzy avatar marwaawd avatar faridaabdelghaffar avatar ramezlahzy avatar saraalajmy avatar nada-abdelfattah avatar

Stargazers

 avatar  avatar  avatar

Forkers

youssof-kandil

copilot-and-sons-pharmacy's Issues

add admin

add admin when user already exists pop up does not show up or no action taken
register as patient also has same problem

send otp

when enter wrong code no action is taken
should have pop up or alert

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.