Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/menathndgd/caresync

CareSync is a modern Patient Management System built with React, Next.js, TailwindCSS, shadcn UI, Appwrite, Sentry, and Twilio. It streamlines patient care by managing appointments, records, and communication, offering real-time notifications and secure data handling.
https://github.com/menathndgd/caresync

Last synced: about 1 month ago
JSON representation

CareSync is a modern Patient Management System built with React, Next.js, TailwindCSS, shadcn UI, Appwrite, Sentry, and Twilio. It streamlines patient care by managing appointments, records, and communication, offering real-time notifications and secure data handling.

Awesome Lists containing this project

README

        





CareSync



A HealthCare Management System



nextdotjs
typescript
tailwindcss
appwrite
shadcn/ui
twilio




CareSync is a modern Patient Management System built with React, Next.js, TailwindCSS, shadcn UI, Appwrite, Sentry, and Twilio. It streamlines patient care by managing appointments, records, and communication, offering real-time notifications and secure data handling.

## πŸ“‹ Table of Contents

1. πŸ€– [Introduction](#introduction)
2. βš™οΈ [Tech Stack](#tech-stack)
3. πŸ”‹ [Features](#features)
4. 🀸 [Quick Start](#quick-start)
5. πŸ•ΈοΈ [Snippets (Code to Copy)](#snippets)
6. πŸ”— [Assets](#links)
7. πŸ“š [More Features Coming Soon](#more)

## πŸ€– Introduction

CareSync is a modern health management platform designed to connect patients and healthcare providers through a seamless, user-friendly interface. The platform enables users to schedule appointments, access medical records, and manage their healthcare needs from one convenient location. With features like real-time notifications, telemedicine, and secure patient data handling, CareSync ensures that managing your healthcare is both efficient and secure.

## βš™οΈ Tech Stack

Our project leverages a modern and robust tech stack to deliver a seamless experience:

- **Next.js**: A powerful React framework for server-side rendering and static site generation.
- **Appwrite**: An open-source backend server to manage database, authentication, and more.
- **TypeScript**: Adds type safety and clarity to our JavaScript code.
- **TailwindCSS**: A utility-first CSS framework for fast and responsive design.
- **ShadCN**: A tool for creating accessible and stylish UI components.
- **Twilio**: A cloud communications platform for SMS, voice, and video integration.

Explore how these technologies come together to power our project!

## πŸ”‹ Features

- 🎯 **Register as a Patient**: Easy sign-up to create personalized patient profiles.

- 🎯 **Book Appointments**: Effortlessly schedule multiple appointments with doctors.

- 🎯 **Admin Appointment Management**: Admins can view, manage, and handle all appointments.

- 🎯 **Confirm/Schedule Appointments**: Admins ensure smooth scheduling and confirmation.

- 🎯 **Cancel Appointments**: Admins can quickly cancel any appointment.

- 🎯 **Appointment SMS Notifications**: Patients receive instant SMS confirmations upon appointment scheduling.

- 🎯 **Responsive Design**: Seamless experience across all devices and screen sizes.

- 🎯 **Secure File Uploads**: Upload files with confidence using Appwrite Storage.

- 🎯 **Performance Tracking**: Monitor and optimize the app’s performance with Sentry.

and many more, including code architecture and reusability.

## 🀸 Quick Start

Follow these steps to set up the project locally on your machine.

**Prerequisites**

Make sure you have the following installed on your machine:

- [Git](https://git-scm.com/)
- [Node.js](https://nodejs.org/en)
- [NPM](https://www.npmjs.com/) (Node Package Manager)

**Cloning the Repository**

```bash
git clone https://github.com/MenathNDGD/CareSync.git
cd CareSync
```

**Installation**

Install the project dependencies using npm:

```bash
npm install
```

**Set Up Environment Variables**

Create a new file named `.env.local` in the root of your project and add the following content:

```env
#APPWRITE
NEXT_PUBLIC_ENDPOINT=https://cloud.appwrite.io/v1
PROJECT_ID=
API_KEY=
DATABASE_ID=
PATIENT_COLLECTION_ID=
APPOINTMENT_COLLECTION_ID=
NEXT_PUBLIC_BUCKET_ID=

NEXT_PUBLIC_ADMIN_PASSKEY=123456
```

Replace the placeholder values with your actual Appwrite credentials. You can obtain these credentials by signing up on the [Appwrite website](https://appwrite.io/).

**Running the Project**

```bash
npm run dev
```

Open [http://localhost:3000](http://localhost:3000) in your browser to view the project.

## πŸ•ΈοΈ Snippets

tailwind.config.ts

```typescript
import type { Config } from "tailwindcss";

const { fontFamily } = require("tailwindcss/defaultTheme");

const config = {
darkMode: ["class"],
content: [
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./app/**/*.{ts,tsx}",
"./src/**/*.{ts,tsx}",
],
prefix: "",
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
green: {
500: "#24AE7C",
600: "#0D2A1F",
},
blue: {
500: "#79B5EC",
600: "#152432",
},
red: {
500: "#F37877",
600: "#3E1716",
700: "#F24E43",
},
light: {
200: "#E8E9E9",
},
dark: {
200: "#0D0F10",
300: "#131619",
400: "#1A1D21",
500: "#363A3D",
600: "#76828D",
700: "#ABB8C4",
},
},
fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans],
},
backgroundImage: {
appointments: "url('/assets/images/appointments-bg.png')",
pending: "url('/assets/images/pending-bg.png')",
cancelled: "url('/assets/images/cancelled-bg.png')",
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
"caret-blink": {
"0%,70%,100%": { opacity: "1" },
"20%,50%": { opacity: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"caret-blink": "caret-blink 1.25s ease-out infinite",
},
},
},
plugins: [require("tailwindcss-animate")],
} satisfies Config;

export default config;
```

app/globals.css

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

/* ========================================== TAILWIND STYLES */
@layer base {
/* Remove scrollbar */
.remove-scrollbar::-webkit-scrollbar {
width: 0px;
height: 0px;
border-radius: 0px;
}

.remove-scrollbar::-webkit-scrollbar-track {
background: transparent;
}

.remove-scrollbar::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 0px;
}

.remove-scrollbar::-webkit-scrollbar-thumb:hover {
/* background: #1e2238; */
background: transparent;
}
}

@layer utilities {
/* ===== UTILITIES */
.sidebar {
@apply remove-scrollbar w-full max-w-72 flex-col overflow-auto bg-black-800 px-7 py-10;
}

.left-sidebar {
@apply hidden lg:flex;
}

.right-sidebar {
@apply hidden xl:flex;
}

.clip-text {
@apply bg-clip-text text-transparent;
}

.bg-image {
@apply bg-black-900 bg-light-rays bg-cover bg-no-repeat;
}

.header {
@apply text-32-bold md:text-36-bold;
}

.sub-header {
@apply text-18-bold md:text-24-bold;
}

.container {
@apply relative flex-1 overflow-y-auto px-[5%];
}

.sub-container {
@apply mx-auto flex size-full flex-col py-10;
}

.side-img {
@apply hidden h-full object-cover md:block;
}

.copyright {
@apply text-14-regular justify-items-end text-center text-dark-600 xl:text-left;
}

/* ==== SUCCESS */
.success-img {
@apply m-auto flex flex-1 flex-col items-center justify-between gap-10 py-10;
}

.request-details {
@apply flex w-full flex-col items-center gap-8 border-y-2 border-dark-400 py-8 md:w-fit md:flex-row;
}

/* ===== ADMIN */
.admin-header {
@apply sticky top-3 z-20 mx-3 flex items-center justify-between rounded-2xl bg-dark-200 px-[5%] py-5 shadow-lg xl:px-12;
}

.admin-main {
@apply flex flex-col items-center space-y-6 px-[5%] pb-12 xl:space-y-12 xl:px-12;
}

.admin-stat {
@apply flex w-full flex-col justify-between gap-5 sm:flex-row xl:gap-10;
}

/* ==== FORM */
.radio-group {
@apply flex h-full flex-1 items-center gap-2 rounded-md border border-dashed border-dark-500 bg-dark-400 p-3;
}

.checkbox-label {
@apply cursor-pointer text-sm font-medium text-dark-700 peer-disabled:cursor-not-allowed peer-disabled:opacity-70 md:leading-none;
}

/* ==== File Upload */
.file-upload {
@apply text-12-regular flex cursor-pointer flex-col items-center justify-center gap-3 rounded-md border border-dashed border-dark-500 bg-dark-400 p-5;
}

.file-upload_label {
@apply flex flex-col justify-center gap-2 text-center text-dark-600;
}

/* ==== Stat Card */
.stat-card {
@apply flex flex-1 flex-col gap-6 rounded-2xl bg-cover p-6 shadow-lg;
}

/* ==== Status Badge */
.status-badge {
@apply flex w-fit items-center gap-2 rounded-full px-4 py-2;
}

/* Data Table */
.data-table {
@apply z-10 w-full overflow-hidden rounded-lg border border-dark-400 shadow-lg;
}

.table-actions {
@apply flex w-full items-center justify-between space-x-2 p-4;
}

/* ===== ALIGNMENTS */
.flex-center {
@apply flex items-center justify-center;
}

.flex-between {
@apply flex items-center justify-between;
}

/* ===== TYPOGRAPHY */
.text-36-bold {
@apply text-[36px] leading-[40px] font-bold;
}

.text-24-bold {
@apply text-[24px] leading-[28px] font-bold;
}

.text-32-bold {
@apply text-[32px] leading-[36px] font-bold;
}

.text-18-bold {
@apply text-[18px] leading-[24px] font-bold;
}

.text-16-semibold {
@apply text-[16px] leading-[20px] font-semibold;
}

.text-16-regular {
@apply text-[16px] leading-[20px] font-normal;
}

.text-14-medium {
@apply text-[14px] leading-[18px] font-medium;
}

.text-14-regular {
@apply text-[14px] leading-[18px] font-normal;
}

.text-12-regular {
@apply text-[12px] leading-[16px] font-normal;
}

.text-12-semibold {
@apply text-[12px] leading-[16px] font-semibold;
}

/* ===== SHADCN OVERRIDES */
.shad-primary-btn {
@apply bg-green-500 text-white !important;
}

.shad-danger-btn {
@apply bg-red-700 text-white !important;
}

.shad-gray-btn {
@apply border border-dark-500 cursor-pointer bg-dark-400 text-white !important;
}

.shad-input-label {
@apply text-14-medium text-dark-700 !important;
}

.shad-input {
@apply bg-dark-400 placeholder:text-dark-600 border-dark-500 h-11 focus-visible:ring-0 focus-visible:ring-offset-0 !important;
}

.shad-input-icon {
@apply bg-dark-400 placeholder:text-dark-600 border-dark-500 h-11 focus-visible:ring-0 focus-visible:ring-offset-0 !important;
}

.shad-textArea {
@apply bg-dark-400 placeholder:text-dark-600 border-dark-500 focus-visible:ring-0 focus-visible:ring-offset-0 !important;
}

.shad-combobox-item {
@apply data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 !important;
}

.shad-combobox-trigger {
@apply h-11 !important;
}

.shad-select-trigger {
@apply bg-dark-400 placeholder:text-dark-600 border-dark-500 h-11 focus:ring-0 focus:ring-offset-0 !important;
}

.shad-select-content {
@apply bg-dark-400 border-dark-500 !important;
}

.shad-dialog {
@apply bg-dark-400 border-dark-500 !important;
}

.shad-dialog button {
@apply focus:ring-0 focus:ring-offset-0 focus-visible:border-none focus-visible:outline-none focus-visible:ring-transparent focus-visible:ring-offset-0 !important;
}

.shad-error {
@apply text-red-400 !important;
}

.shad-table {
@apply rounded-lg overflow-hidden !important;
}

.shad-table-row-header {
@apply border-b border-dark-400 text-light-200 hover:bg-transparent !important;
}

.shad-table-row {
@apply border-b border-dark-400 text-light-200 !important;
}

.shad-otp {
@apply w-full flex justify-between !important;
}

.shad-otp-slot {
@apply text-36-bold justify-center flex border border-dark-500 rounded-lg size-16 gap-4 !important;
}

.shad-alert-dialog {
@apply space-y-5 bg-dark-400 border-dark-500 outline-none !important;
}

.shad-sheet-content button {
@apply top-2 focus:ring-0 focus:ring-offset-0 focus-visible:border-none focus-visible:outline-none focus-visible:ring-transparent focus-visible:ring-offset-0 !important;
}

/* ===== REACT PHONE NUMBER INPUT OVERRIDES */
.input-phone {
@apply mt-2 h-11 rounded-md px-3 text-sm border bg-dark-400 placeholder:text-dark-600 border-dark-500 !important;
}

/* ===== REACT DATE PICKER OVERRIDES */
.date-picker {
@apply overflow-hidden border-transparent w-full placeholder:text-dark-600 h-11 text-14-medium rounded-md px-3 outline-none !important;
}
}

/* ===== REACT-DATEPICKER OVERRIDES */
.react-datepicker-wrapper.date-picker {
display: flex;
align-items: center;
}

.react-datepicker,
.react-datepicker__time,
.react-datepicker__header,
.react-datepicker__current-month,
.react-datepicker__day-name,
.react-datepicker__day,
.react-datepicker-time__header {
background-color: #1a1d21 !important;
border-color: #363a3d !important;
color: #abb8c4 !important;
}

.react-datepicker__current-month,
.react-datepicker__day-name,
.react-datepicker-time__header {
color: #ffffff !important;
}

.react-datepicker__triangle {
fill: #1a1d21 !important;
color: #1a1d21 !important;
stroke: #1a1d21 !important;
}

.react-datepicker__time-list-item:hover {
background-color: #363a3d !important;
}

.react-datepicker__input-container input {
background-color: #1a1d21 !important;
width: 100%;
outline: none;
}

.react-datepicker__day--selected {
background-color: #24ae7c !important;
color: #ffffff !important;
border-radius: 4px;
}

.react-datepicker__time-list-item--selected {
background-color: #24ae7c !important;
}

.react-datepicker__time-container {
border-left: 1px solid #363a3d !important;
}

.react-datepicker__time-list-item {
display: flex !important;
align-items: center !important;
}

/* ===== REACT PHONE NUMBER INPUT OVERRIDES */
.PhoneInputInput {
outline: none;
margin-left: 4px;
background: #1a1d21;
font-size: 14px;
font-weight: 500;
}

.PhoneInputInput::placeholder {
color: #1a1d21;
}
```

types/index.d.ts

```typescript
/* eslint-disable no-unused-vars */

declare type SearchParamProps = {
params: { [key: string]: string };
searchParams: { [key: string]: string | string[] | undefined };
};

declare type Gender = "Male" | "Female" | "Other";
declare type Status = "pending" | "scheduled" | "cancelled";

declare interface CreateUserParams {
name: string;
email: string;
phone: string;
}
declare interface User extends CreateUserParams {
$id: string;
}

declare interface RegisterUserParams extends CreateUserParams {
userId: string;
birthDate: Date;
gender: Gender;
address: string;
occupation: string;
emergencyContactName: string;
emergencyContactNumber: string;
primaryPhysician: string;
insuranceProvider: string;
insurancePolicyNumber: string;
allergies: string | undefined;
currentMedication: string | undefined;
familyMedicalHistory: string | undefined;
pastMedicalHistory: string | undefined;
identificationType: string | undefined;
identificationNumber: string | undefined;
identificationDocument: FormData | undefined;
privacyConsent: boolean;
}

declare type CreateAppointmentParams = {
userId: string;
patient: string;
primaryPhysician: string;
reason: string;
schedule: Date;
status: Status;
note: string | undefined;
};

declare type UpdateAppointmentParams = {
appointmentId: string;
userId: string;
appointment: Appointment;
type: string;
};
```

types/appwrite.types.ts

```typescript
import { Models } from "node-appwrite";

export interface Patient extends Models.Document {
userId: string;
name: string;
email: string;
phone: string;
birthDate: Date;
gender: Gender;
address: string;
occupation: string;
emergencyContactName: string;
emergencyContactNumber: string;
primaryPhysician: string;
insuranceProvider: string;
insurancePolicyNumber: string;
allergies: string | undefined;
currentMedication: string | undefined;
familyMedicalHistory: string | undefined;
pastMedicalHistory: string | undefined;
identificationType: string | undefined;
identificationNumber: string | undefined;
identificationDocument: FormData | undefined;
privacyConsent: boolean;
}

export interface Appointment extends Models.Document {
patient: Patient;
schedule: Date;
status: Status;
primaryPhysician: string;
reason: string;
note: string;
userId: string;
cancellationReason: string | null;
}
```

lib/utils.ts

```typescript
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}

export const parseStringify = (value: any) => JSON.parse(JSON.stringify(value));

export const convertFileToUrl = (file: File) => URL.createObjectURL(file);

// FORMAT DATE TIME
export const formatDateTime = (dateString: Date | string) => {
const dateTimeOptions: Intl.DateTimeFormatOptions = {
// weekday: "short", // abbreviated weekday name (e.g., 'Mon')
month: "short", // abbreviated month name (e.g., 'Oct')
day: "numeric", // numeric day of the month (e.g., '25')
year: "numeric", // numeric year (e.g., '2023')
hour: "numeric", // numeric hour (e.g., '8')
minute: "numeric", // numeric minute (e.g., '30')
hour12: true, // use 12-hour clock (true) or 24-hour clock (false)
};

const dateDayOptions: Intl.DateTimeFormatOptions = {
weekday: "short", // abbreviated weekday name (e.g., 'Mon')
year: "numeric", // numeric year (e.g., '2023')
month: "2-digit", // abbreviated month name (e.g., 'Oct')
day: "2-digit", // numeric day of the month (e.g., '25')
};

const dateOptions: Intl.DateTimeFormatOptions = {
month: "short", // abbreviated month name (e.g., 'Oct')
year: "numeric", // numeric year (e.g., '2023')
day: "numeric", // numeric day of the month (e.g., '25')
};

const timeOptions: Intl.DateTimeFormatOptions = {
hour: "numeric", // numeric hour (e.g., '8')
minute: "numeric", // numeric minute (e.g., '30')
hour12: true, // use 12-hour clock (true) or 24-hour clock (false)
};

const formattedDateTime: string = new Date(dateString).toLocaleString(
"en-US",
dateTimeOptions
);

const formattedDateDay: string = new Date(dateString).toLocaleString(
"en-US",
dateDayOptions
);

const formattedDate: string = new Date(dateString).toLocaleString(
"en-US",
dateOptions
);

const formattedTime: string = new Date(dateString).toLocaleString(
"en-US",
timeOptions
);

return {
dateTime: formattedDateTime,
dateDay: formattedDateDay,
dateOnly: formattedDate,
timeOnly: formattedTime,
};
};

export function encryptKey(passkey: string) {
return btoa(passkey);
}

export function decryptKey(passkey: string) {
return atob(passkey);
}
```

lib/validation.ts

```typescript
import { z } from "zod";

export const UserFormValidation = z.object({
name: z
.string()
.min(2, "Name must be at least 2 characters")
.max(50, "Name must be at most 50 characters"),
email: z.string().email("Invalid email address"),
phone: z
.string()
.refine((phone) => /^\+\d{10,15}$/.test(phone), "Invalid phone number"),
});

export const PatientFormValidation = z.object({
name: z
.string()
.min(2, "Name must be at least 2 characters")
.max(50, "Name must be at most 50 characters"),
email: z.string().email("Invalid email address"),
phone: z
.string()
.refine((phone) => /^\+\d{10,15}$/.test(phone), "Invalid phone number"),
birthDate: z.coerce.date(),
gender: z.enum(["Male", "Female", "Other"]),
address: z
.string()
.min(5, "Address must be at least 5 characters")
.max(500, "Address must be at most 500 characters"),
occupation: z
.string()
.min(2, "Occupation must be at least 2 characters")
.max(500, "Occupation must be at most 500 characters"),
emergencyContactName: z
.string()
.min(2, "Contact name must be at least 2 characters")
.max(50, "Contact name must be at most 50 characters"),
emergencyContactNumber: z
.string()
.refine(
(emergencyContactNumber) => /^\+\d{10,15}$/.test(emergencyContactNumber),
"Invalid phone number"
),
primaryPhysician: z.string().min(2, "Select at least one doctor"),
insuranceProvider: z
.string()
.min(2, "Insurance name must be at least 2 characters")
.max(50, "Insurance name must be at most 50 characters"),
insurancePolicyNumber: z
.string()
.min(2, "Policy number must be at least 2 characters")
.max(50, "Policy number must be at most 50 characters"),
allergies: z.string().optional(),
currentMedication: z.string().optional(),
familyMedicalHistory: z.string().optional(),
pastMedicalHistory: z.string().optional(),
identificationType: z.string().optional(),
identificationNumber: z.string().optional(),
identificationDocument: z.custom().optional(),
treatmentConsent: z
.boolean()
.default(false)
.refine((value) => value === true, {
message: "You must consent to treatment in order to proceed",
}),
disclosureConsent: z
.boolean()
.default(false)
.refine((value) => value === true, {
message: "You must consent to disclosure in order to proceed",
}),
privacyConsent: z
.boolean()
.default(false)
.refine((value) => value === true, {
message: "You must consent to privacy in order to proceed",
}),
});

export const CreateAppointmentSchema = z.object({
primaryPhysician: z.string().min(2, "Select at least one doctor"),
schedule: z.coerce.date(),
reason: z
.string()
.min(2, "Reason must be at least 2 characters")
.max(500, "Reason must be at most 500 characters"),
note: z.string().optional(),
cancellationReason: z.string().optional(),
});

export const ScheduleAppointmentSchema = z.object({
primaryPhysician: z.string().min(2, "Select at least one doctor"),
schedule: z.coerce.date(),
reason: z.string().optional(),
note: z.string().optional(),
cancellationReason: z.string().optional(),
});

export const CancelAppointmentSchema = z.object({
primaryPhysician: z.string().min(2, "Select at least one doctor"),
schedule: z.coerce.date(),
reason: z.string().optional(),
note: z.string().optional(),
cancellationReason: z
.string()
.min(2, "Reason must be at least 2 characters")
.max(500, "Reason must be at most 500 characters"),
});

export function getAppointmentSchema(type: string) {
switch (type) {
case "create":
return CreateAppointmentSchema;
case "cancel":
return CancelAppointmentSchema;
default:
return ScheduleAppointmentSchema;
}
}
```

constants/index.ts

```typescript
export const GenderOptions = ["Male", "Female", "Other"];

export const PatientFormDefaultValues = {
firstName: "",
lastName: "",
email: "",
phone: "",
birthDate: new Date(Date.now()),
gender: "Male" as Gender,
address: "",
occupation: "",
emergencyContactName: "",
emergencyContactNumber: "",
primaryPhysician: "",
insuranceProvider: "",
insurancePolicyNumber: "",
allergies: "",
currentMedication: "",
familyMedicalHistory: "",
pastMedicalHistory: "",
identificationType: "Birth Certificate",
identificationNumber: "",
identificationDocument: [],
treatmentConsent: false,
disclosureConsent: false,
privacyConsent: false,
};

export const IdentificationTypes = [
"Birth Certificate",
"Driver's License",
"Medical Insurance Card/Policy",
"Military ID Card",
"National Identity Card",
"Passport",
"Resident Alien Card (Green Card)",
"Social Security Card",
"State ID Card",
"Student ID Card",
"Voter ID Card",
];

export const Doctors = [
{
image: "/assets/images/dr-green.png",
name: "John Green",
},
{
image: "/assets/images/dr-cameron.png",
name: "Leila Cameron",
},
{
image: "/assets/images/dr-livingston.png",
name: "David Livingston",
},
{
image: "/assets/images/dr-peter.png",
name: "Evan Peter",
},
{
image: "/assets/images/dr-powell.png",
name: "Jane Powell",
},
{
image: "/assets/images/dr-remirez.png",
name: "Alex Ramirez",
},
{
image: "/assets/images/dr-lee.png",
name: "Jasmine Lee",
},
{
image: "/assets/images/dr-cruz.png",
name: "Alyana Cruz",
},
{
image: "/assets/images/dr-sharma.png",
name: "Hardik Sharma",
},
];

export const StatusIcon = {
scheduled: "/assets/icons/check.svg",
pending: "/assets/icons/pending.svg",
cancelled: "/assets/icons/cancelled.svg",
};
```

## πŸ”— Assets

Access all the public assets used in the project, including images, icons, and other media files, from our shared drive. Feel free to download and explore them:

[Click here to view and download assets](https://drive.google.com/file/d/1yGvWFeSaH1_-aiQ1gejT23lqz5979RKB/view?usp=sharing)

We've updated our logo for a more modern and refreshing look! The new **CareSync** logo represents our commitment to delivering cutting-edge healthcare management. Here's how to update it in your project:

Replace **logo-full.svg** with **logo-full.png**:

1. Navigate to the `/public/assets/icons/` folder.
2. Delete `logo-full.svg`.
3. Add the new **CareSync** logo as `logo-full.png`.

This new logo aligns perfectly with our mission of simplifying healthcare management. Check it out and let us know what you think!

## πŸ“š More Features Coming Soon

We’re continually enhancing CareSync to provide the best experience possible. Here’s what you can expect in future updates:

- 🌟 **Telemedicine**: Virtual doctor consultations within the app.
- 🌟 **In-depth Analytics**: Comprehensive reports on patient records and appointment trends.
- 🌟 **Advanced Security**: Two-factor authentication for enhanced security.
- 🌟 **Health Reminders**: Personalized notifications for medication, appointments, and more.
- 🌟 **Integration with Wearables**: Sync health data from smartwatches and fitness trackers.

Stay tuned for more exciting features and improvements! πŸš€

#