MediPhase is a surgery status app that helps medical teams monitor a patient's surgery journey with ease. MediPhase provides real-time updates on surgical patient status.
MediPhase offers simple, secure, and compassionate care at your medical team's fingertips.
Deployed App: https://v56-tier2-team-22.vercel.app/sign-in
As part of Chingu Voyage 56, our team, Team 22, built MediPhase as a Frontend Project.
Given a project spec for a surgery status board, over the course of 6 weeks, everyone on the team contributed 8-12 hours of work to the project. The team collaborated by employing agile methodologies, implementing standups and weekly sprint planning and retro meetings as well as pair programming sessions. We took a spec to a functioning, deployed app.
The main feature of MediPhase is a dashboard that communicates with Guest users in a surgery waiting room or via web application what phase of the surgery their loved-one is in:
Checked In
Pre-Procedure
In-Progress
Closing
Recovery
Complete
Once a patient's status is updated to Dismissed
, the patient is removed from the screen.
Admin users are able to create, view and update patient information, including what status a patient is in in their surgery.
Surgical Staff users are able to lookup a patient by ID number and update their surgical status.
Mediphase uses the following tech stack and core dependencies:
The project is organized as follows:
/src
/assets # Static assets (images, icons, etc.)
/components # Reusable UI components and shared logic
/PatientStatusTable # Patient table, forms, and related components
/Footer # Footer and related components
/ui # UI primitives (buttons, inputs, etc.)
...
/constant # Static constants and configuration
/contexts # React Context providers (e.g., user role)
/hooks # Custom React hooks
/layout # Layout components (wrappers, containers)
/lib # Utility functions and helpers
/screens # Top-level pages/screens (AddPatient, UpdateInfo, etc.)
App.tsx # Main app component
main.tsx # App entry point
routes.tsx # Route definitions
index.css # Global styles
- /src/screens: Each screen/page in the app (e.g., AddPatient, UpdateInfo, PatientStatusBoard).
- /src/components: Reusable components, grouped by feature or type.
- /src/hooks: Custom hooks for shared logic.
- /src/contexts: Context providers for global state (e.g., user authentication).
- /src/constant: Static data and configuration.
- /src/layout: Layout components for consistent page structure.
- /src/lib: Utility functions and helpers.
- /src/assets: Images and other static files.
This structure helps keep code modular, maintainable, and easy to navigate as the project grows.
-
This project uses React's Context API to manage and globally store the current user role within the application during the user's session.
-
Once a user logs in, their role (e.g., Admin, Surgical Staff) is saved to Local Storage. This stored role is then used to authorize and control which routes and features the user can access throughout the app.
-
Patient data is initially loaded from a static JSON object, but any updates (such as adding, editing, or dismissing a patient) are saved to the browser's Local Storage. This ensures that changes to patient data persist across page refreshes during the user's session.
-
On app load, the patient data is retrieved from Local Storage if available; otherwise, it falls back to the default JSON data.
-
As a more frontend-focused app, we decided to use Local Storage for any data that needs to be persisted across page refreshes.
- Role-based Functionality:
- Admin users can add, view, and update patient information, including updating patient status.
- Surgical Staff users can look up patients by ID and update their surgical status.
- Guest users can view the current status of patients but cannot make changes.
- Real-time Patient Status Dashboard:
- All users can view a dashboard showing the current status of patients as they move through each phase of surgery.
- Patients are automatically removed from the dashboard when their status is updated to
Dismissal
.
-
Context API for User Authentication and Role Management:
The app uses React’s Context API to manage authentication state and user roles globally, enabling role-based routing and feature access.View code
// src/contexts/AuthContext.tsx export const AuthContext = createContext<AuthContextType | null>(null); export const AuthProvider = ({ children }: { children: React.ReactNode }) => { const [user, setUser] = useState<User>(() => { const storedUser = localStorage.getItem('user'); return storedUser ? JSON.parse(storedUser) : null; }); useEffect(() => { if (user) { localStorage.setItem('user', JSON.stringify(user)); } else { localStorage.removeItem('user'); } }, [user]); const signIn = (email: string, password: string) => { const storedUser = users.find((credential) => credential.email === email); if (!storedUser) { return Promise.reject(new AuthError(INVALID_EMAIL_MSG)); } if (storedUser.password !== password) { return Promise.reject(new AuthError(INVALID_PASSWORD_MSG)); } //eslint-disable-next-line const { password: _, ...userProps } = storedUser as User & { password: string; }; setUser(userProps); return Promise.resolve(userProps); }; const signInAsGuest = () => setUser({ id: uuidv4(), role: 'guest', }); const signOut = () => setUser(null); return ( <AuthContext.Provider value={{ user, signIn, signInAsGuest, signOut }}> {children} </AuthContext.Provider> ); };
-
Local Storage for Data Persistence:
Patient data and user roles are stored in browser Local Storage.
Patient data is initially loaded from a static JSON object, but any changes (add, edit, dismiss) are saved to Local Storage, so updates persist across page refreshes. An example of this is theupdatePatientStatus
method.View code
// src/utility/patientHelpers.ts export function updatePatientStatus(id: string, newStatus: string) { const patients = JSON.parse(localStorage.getItem("patients") || "[]"); console.log("Before update:", patients); const idx = patients.findIndex((p: Patient) => p.id === id); if (idx !== -1) { patients[idx].status = newStatus; // Lookup color/message const statusMetaData = statusInfo.find(s => s.status === newStatus); if (statusMetaData) { patients[idx].color = statusMetaData.color; patients[idx].message = statusMetaData.message; } localStorage.setItem("patients", JSON.stringify(patients)); console.log("After update:", patients); return patients[idx]; } return null; }
-
Automatic Table Pagination:
The patient dashboard uses TanStack Table for flexible, filterable, and paginated data display.
In auto mode, the table automatically moves to the next page after 20 seconds, allowing users in waiting rooms to see all patients in rotation without manual interaction.View code
// src/components/PatientStatusTable/PaginationController.tsx // auto pagination every 15 seconds useEffect(() => { if (paginationMode !== 'auto') { setCountdown(20); return; } setCountdown(20); if (paginationMode !== 'auto') return; const interval = setInterval(() => { setCountdown((prev) => { if (prev <= 1) { const currentPageIndex = table.getState().pagination.pageIndex; const pageCount = table.getPageCount(); if (pageCount > 0) { if (currentPageIndex < pageCount - 1) { table.nextPage(); } else { table.setPageIndex(0); } } return 20; } return prev - 1; }); }, 1000); return () => clearInterval(interval); }, [paginationMode, table]);
-
Dynamic Table and Forms:
The patient dashboard uses TanStack Table for flexible, filterable, and paginated data display. Forms for adding and updating patients use React Hook Form and Zod for validation and type safety. -
Responsive UI:
The app is built with Tailwind CSS and shadcn/ui primitives for a modern, accessible, and responsive design.
Clone the repository locally:
git clone https://github.com/chingu-voyages/V56-tier2-team-22.git
If not already there, navigate to the project folder:
cd v56-team22-surgery-status-board
Install dependencies:
npm install
or npm i
Run the app:
npm run dev
To access features on protected routes dedicated to Admin and Surgical Staff users, use the following credentials:
Admin User
Email: admin@mediphase.com
Password: admin
Surgical Staff User
Email:surgeon@mediphase.com
Password:surgeon
With every project, there are always stretch goals that are out of reach when the deadline arrives.
Here are a few TODOs that are left at the end of the project:
- Playwright or Cypress Testing: There was an idea to add frontend testing to the app, but it wasn't completed by the deadline.
- Gemini AI Integration with a Chatbot (the chatbot is designed, not implemented).
We are 4 developers living in 4 different countries brought together by Chingu Voyage 56 in early July 2025.
Before being accepted to the Voyage, we all completed a Solo Project.
- Rachel Tipton: GitHub / LinkedIn
- Mohamed Ouederni: GitHub / LinkedIn
- Avtar Singh: GitHub / LinkedIn
- Rapha Chris: Github / LinkedIn
It's hard to dedicate time in a busy schedule to a side project. And everyone on Team 22 showed up week after week to code, refine and complete tickets, reflect on how the process was going, review code and build together.
Here are the wins our team had over the course of the voyage:
- Building an app in community with others and sharing our knowledge with each other.
- Gaining a better understanding of Agile Methodologies in practice.
Chingu projects are often assigned a Product Owner or a Voyage Guide. Our team didn't have either of these, so the members of the team that had more professional experience stepped in to organize and run planning meetings, set up a GitHub Project for Product Backlog, etc. This is not always easy when everybody just wants to jump in and code.