You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A production-ready Flutter medical app that connects patients with doctors across multiple specializations. Patients can browse specializations, search and filter doctors, view detailed profiles, book appointments with real-time slot selection, and communicate with doctors through a real-time chat inbox powered by Firebase Firestore.
Built with Clean Architecture, BLoC/Cubit state management, Retrofit + Dio networking, and GetIt dependency injection.
📸 Application Screenshots
🚀 Onboarding & Authentication
Splash
Onboarding
Login
Register
Splash Screen
Onboarding
Login
Register
🏠 Home & Discovery
Home
Find Doctors
Specialties
Doctors List
Home
Find Doctors
Specialties
Doctors List
Search
Filter Doctors
Search
Filter Doctors
👨⚕️ Doctor Details
Doctor Details
Reviews
Location
Overview
Reviews
Location
📅 Appointment Booking
Appointment Booking
Appointment Summary
Payment
Success
Select Time
Summary
Payment
Success
💬 Messaging & Notifications
Inbox
Chat Conversation
Appointments
Inbox
Chat Conversation
Appointments List
🩺 Medical Records & Payments
Medical Records
Payments
Medical Records
Payments
👤 Profile Management
Profile
Edit Profile
Profile
Edit Profile
⚙️ Settings & Security
Settings
Security
Notification Settings
FAQs
Settings
Security
Notification Settings
FAQs
Logout
Logout
Key Features
Authentication — Login & registration with JWT-based auth, secure token storage via flutter_secure_storage, and persistent login state
Doctor Browsing — Browse 15+ medical specializations (Cardiology, Dentistry, Neurology, Pediatrics, etc.) with specialty-specific doctor listings
Doctor Search & Sort — Search doctors by name with debounced input, sort by name (A-Z / Z-A) or specialization via a reusable bottom sheet
Doctor Details — Detailed profiles showing qualifications, contact info, availability windows, and patient reviews with star ratings
Appointment Booking — Time-slot picker generated from each doctor's working hours, with booking confirmation flow
Nearby Doctors — Location-aware listing of doctors near the patient with map integration
Real-Time Inbox — Firebase Firestore-powered messaging with live conversation streams, unread indicators, and last-message previews
Chat Thread — Full conversation UI with sent/received message bubbles, session tags, and a rich input bar (attachments, camera, emoji)
New Message — Doctor suggestion sheet with search/sort to start new conversations
Notifications — In-app notification center for appointment updates and system alerts
Multi-Flavor Builds — Separate development and production entry points with independent configurations
Responsive UI — Fully responsive layouts using flutter_screenutil for consistent sizing across devices
Tech Stack
Concern
Technology
Framework
Flutter / Dart 3.x
State Management
flutter_bloc / Cubit
Networking
Retrofit + Dio
Dependency Injection
GetIt
Code Generation
Freezed, json_serializable, retrofit_generator
Real-Time Database
Cloud Firestore (Firebase)
Secure Storage
flutter_secure_storage
Local Storage
shared_preferences
JWT Decoding
jwt_decoder
Image Caching
cached_network_image
SVG Rendering
flutter_svg
Loading Skeletons
shimmer
Responsive Sizing
flutter_screenutil
Localization
easy_localization + intl
Splash Screen
flutter_native_splash
HTTP Logging
pretty_dio_logger
Architecture
The app follows a feature-first architecture with clear separation between data, business logic, and presentation layers.
State is consumed via BlocBuilder / BlocSelector scoped to only the subtree that needs rebuilding — static UI elements (navbars, search bars) sit outside the builder to avoid unnecessary rebuilds.
API & Data Layer
REST API — Backed by the vcare API (https://vcare.integration25.com/api/) using Retrofit-generated type-safe HTTP clients
Firebase Firestore — Real-time messaging with snapshots() streams for live conversation updates
Error Handling — Unified ApiResult<T> Freezed union (Success | Failure) wrapping all API calls, with ErrorHandler converting Dio exceptions into structured ApiErrorModel
JWT Auth — Token stored in flutter_secure_storage, injected into Dio headers via DioFactory.setTokenIntoHeadersAfterLogin()
Security Practices
Auth tokens stored in encrypted secure storage (flutter_secure_storage), never in plain SharedPreferences
JWT decoded client-side only for user identification (jwt_decoder), never for authorization decisions
API requests authenticated via Bearer token injected at the Dio interceptor level
Sensitive vs. non-sensitive data separated: flutter_secure_storage for tokens, shared_preferences for UI preferences only
Performance Optimizations
RepaintBoundary on repeated list items — each card's shadow/decoration is rasterized independently
BlocSelector scoping — only the subtree that depends on state rebuilds; static chrome (navbars, search bars) stays outside
ListView.builder / .separated for all dynamic lists — never ListView(children: [...]) which builds every item upfront
memCacheWidth / memCacheHeight on cached images — prevents decoding full-resolution bitmaps into small display boxes
Debounced search input — API calls fire only after the user stops typing, not on every keystroke
IndexedStack for bottom navigation — preserves page state across tab switches without rebuilding
Getting Started
Prerequisites
Flutter SDK ^3.11.1
Dart ^3.11.1
Firebase project configured (Firestore enabled)
iOS: CocoaPods installed
Android: Android SDK with minimum API level configured
Installation
# 1. Clone the repository
git clone https://github.com/your-username/doc-doc.git
cd doc-doc
# 2. Install dependencies
flutter pub get
# 3. Generate code (Freezed, Retrofit, json_serializable)
dart run build_runner build --delete-conflicting-outputs
# 4. Run the app (development flavor)
flutter run -t lib/main_development.dart
# 5. Run the app (production flavor)
flutter run -t lib/main_production.dart
Other Commands
# Watch and regenerate on file changes
dart run build_runner watch --delete-conflicting-outputs
# Static analysis
flutter analyze
# Run tests
flutter test
Engineering Highlights
Strengths
Dual data source architecture — REST API for medical data + Firebase Firestore for real-time messaging, cleanly separated through the repository pattern
Reusable component design — Search bar and sort sheet widgets are decoupled from any specific Cubit, accepting callbacks so they work across Doctors, New Message, and Inbox screens
Type-safe networking — Retrofit generates HTTP clients from annotations; Freezed generates sealed unions for state — zero hand-written boilerplate for API calls or state transitions
Performance-first list rendering — RepaintBoundary, BlocSelector scoping, memCacheWidth, and ListView.builder applied consistently across all data-heavy screens
Challenges Solved
Cubit context scoping — Resolved BlocProvider lookup failures in modal bottom sheets by extracting child widgets to ensure the correct BuildContext is used for provider lookup
Reusable sort/filter architecture — Refactored tightly-coupled sort sheet from single-Cubit dependency to a callback-based pattern, enabling reuse across three different screens without code duplication
Dual API format error handling — Server returns errors in two formats ({ message, code, data } and plain string); ErrorHandler normalizes both into a single ApiErrorModel
Known Trade-offs
Chat messages are currently static sample data — Firestore message read/write is wired at the conversation level but not yet at the individual message level
Three bottom navigation tabs (Search, Appointments, Profile) are placeholder screens pending implementation
Test coverage is minimal — architecture supports testing through DI and repository abstraction, but unit/widget tests are not yet written