- Demo
- Tech Stack
- How it works
- Getting Started Locally
- Api Helpers
- Interfaces
- Types
- Auth Class
- Patient Class
- TODO
View the Demo
The Patient Management Dashboard is built using the following technologies:
- Next.js: A React framework for building server-side rendered and statically generated web applications.
- TypeScript: A typed superset of JavaScript that adds static types to the language.
- Tailwind CSS: A utility-first CSS framework that provides a set of pre-designed styles and classes for building responsive user interfaces.
- Next.js Server Routes: We use Next.js server routes as the backend for handling API requests and serving data to the front-end. Next.js server routes provide an easy way to create API endpoints and interact with our Firebase Firestore database.
- Firebase: A cloud-based platform by Google that provides services for building and managing web and mobile applications. We are using Firebase Firestore as the database for storing patient and user data.
- Firebase Authentication: Firebase's authentication service that provides easy-to-use authentication for our web app. We support authentication with email & password and OAuth providers like Google.
- Vercel: A platform for deploying and hosting web applications. We use Vercel to deploy the Patient Management Dashboard.
View the Demo
- Git: A distributed version control system used for tracking changes in our codebase and collaborating with multiple developers.
- Vercel: Our deployment platform also offers CI/CD capabilities, enabling us to automatically build and deploy changes to production.
- Husky: A tool that allows us to add git hooks to our project. We use Husky to set up a pre-commit hook to run ESLint on staged files before committing.
- lint-staged: A tool that runs linters on only the files that are staged for committing. We use lint-staged in conjunction with Husky to ensure that only properly formatted code is committed to the repository.
- ESLint: A popular JavaScript and TypeScript linter that helps us maintain consistent code style and catch potential issues.
- Sign up Here
- Add a patient by clicking the blue button labelled
Add patient
- Add multiple addresses by clicking
Add address
- Add custom fields by clicking
Add custom field
; Select the field type eithertext
ornumber
- Hit
Add patient
to save the new patient - Click on the patient in the table to open their information, there you can edit and delete the patient
- To filter patients you can click the
Filter
button near theAdd patient
button - On the side panel you can select multiple filters
- You can filter for dates after a certain date by only entering the
from
date - You can search for dates before a certain date by only entering the
to
date - If you want to search between dates enter both
from
andto
dates - Click
Clear
if you need to clear the dates. CAUTION: This will reset all the active filters - Click
Apply
to apply the filters - You can then refine the search by using the search bar, this will search through all fields including the patient's name, dob, addresses, and custom fields
First, install the dependencies:
yarn
Open http://localhost:3000 with your browser to see the result.
Next add your firebase config to your .env.local file:
NEXT_PUBLIC_FIREBASE_APIKEY==""
NEXT_PUBLIC_FIREBASE_AUTHDOMAIN=""
NEXT_PUBLIC_FIREBASE_PROJECTID=""
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=""
NEXT_PUBLIC_FIREBASE_MESSEGE_SENDER_ID=""
NEXT_PUBLIC_FIREBASE_APP_ID=""
Start the project:
yarn dev
Api methods can be accessed as a service.
Example:
import * as api from "utils/helpers/api";
// Example
const addNewPatient = async (values: IPatient) => {
try {
await api.patient.create(values);
} catch (err) {
console.log("ERROR Failed to create patient", err);
}
};
interface IUser {
id: string;
email: string;
firstName?: string;
lastName?: string;
fullName?: string;
}
interface IErrorMessage {
success: boolean;
message: string;
code?: string;
data?: any;
}
interface NotificationProps {
text?: string;
href?: string;
ctaText?: string;
variant?: TNotificationVariants;
}
interface INotification {
show: boolean;
text?: string;
href?: string;
ctaText?: string;
variant?: TNotificationVariants;
delay?: number;
}
interface ISelectOption {
label: string;
value: string;
}
interface IName {
first: string;
middle: string;
last: string;
}
interface IAddress {
primary: boolean;
street: string;
streetNumber: string;
city: string;
province: string;
country: string;
postalCode: string;
}
interface IPatient {
id: string;
name: IName;
dob: string;
status: TStatusFilterOption;
addresses?: IAddress[];
additionalFields?: {
fieldType: TFieldTypes;
fieldValue: string;
fieldLabel: string;
}[];
}
interface IPatientFilters {
status: TStatusFilterOption[];
dob: string[];
cities: string[];
provinces: string[];
}
type TNotificationVariants = "default" | "success" | "error";
type TPatientFilterHandler<IPatient> = (patient: IPatient) => boolean;
type TStatusFilterOption = "inquiry" | "onboarding" | "active" | "churned";
type TFieldTypes = "text" | "number";
The Auth
class is a utility class used for handling authentication logic. It provides methods to handle user login, signup, and sign-out, as well as methods to fetch and create user data.
class Auth {
user?: IUser;
error?: IErrorMessage;
constructor(user?: IUser, error?: IErrorMessage);
handleError(err: any): IErrorMessage;
async loginWithEmail(email: string, password: string): Promise<any>;
async loginWithProvider(): Promise<any>;
async createUserWithEmail(email: string, password: string): Promise<any>;
async signup(
provider: "google" | "email",
email?: string,
password?: string
): Promise<any>;
async signOut(): Promise<any>;
async get(id: string): Promise<IUser | IErrorMessage>;
async create(
id: string,
email: string,
extraFields?: IUser
): Promise<IUser | IErrorMessage>;
}
export default Auth;
// Handle and format error responses from Firebase Authentication.
handleError(err: any): IErrorMessage {
// Implementation here...
}
Authenticate user using email and password.
Authenticate user using a provider (Google). Opens a popup for account selection.
Create a new user account using email and password.
Sign up a user. If provider is 'email', create a new user account using email and password. If provider is 'google', sign in using Google provider and create a user account if it's a new user.
Sign out the authenticated user.
Fetch user data by ID from the server.
Create a user account with the provided ID and email on the server. Optionally, additional user fields can be provided in extraFields.
The Patient
class is a utility class used for handling patient-related operations. It provides methods to fetch patient data, create a new patient, update patient information, and list all patients.
class Patient {
id: string;
name: IName;
dob: string;
status: TStatusFilterOption;
addresses?: IAddress[];
additionalFields?: {
fieldType: TFieldTypes;
fieldValue: string;
fieldLabel: string;
}[];
constructor(patient?: IPatient);
set(patient: IPatient);
async get(id: string): Promise<IPatient | IErrorMessage>;
async create(patientData: IPatient): Promise<IPatient | IErrorMessage>;
async update(patientData: IPatient): Promise<IPatient | IErrorMessage>;
async list(): Promise<IPatient[] | IErrorMessage>;
}
export default Patient;
Set patient data from the provided patient object.
Fetch patient data by ID from the server and set it in the Patient instance.
Create a new patient record on the server with the provided patientData and set it in the Patient instance.
Update patient data on the server with the provided patientData.
Delete patient data on the server with the provided patientId.
Fetch a list of all patients from the server and return an array of patient data.
- Permission based auth to only view patients that would be specific to the user if applicable. Depending on the application if it's used for a clinic as a whole or many independent clinics it would need to be set up accordingly.