Skip to content

PanagiotisKaraliolios/medication-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

76 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

💊 MediTrack — Medication Tracker

A modern, full-featured medication tracking app built with Expo and React Native. Track medications, set smart reminders, monitor adherence, and stay on top of your health — all from your phone.

Expo SDK 55 React Native TypeScript Supabase TanStack Query Biome


📱 Screenshots

Today Dashboard    Medications List    Reports & Analytics    Profile

Today Dashboard  ·  Medications  ·  Reports  ·  Profile


✨ Features

📋 Medication Management

  • Add, edit, and archive medications with name, dosage, form, and custom icons
  • Track current supply with visual progress bars and low-supply alerts
  • Support for all common medication forms (tablet, capsule, liquid, injection, etc.)
  • PRN (as-needed) medications — log doses on demand without a fixed schedule

💊 Drug Database & Interactions

  • Search the RxNorm drug database with autocomplete
  • Auto-fill medication name and generic name from search results
  • Drug interaction checker — warns about potential interactions between your medications

⏰ Smart Scheduling

  • Flexible frequency options — daily, specific days, or custom interval (every N days)
  • Multiple time slots per day (Morning, Afternoon, Evening, Night, or custom times)
  • Start and end date support for limited-duration medications
  • Configurable snooze durations per schedule
  • Unified flow: add a medication and schedule it in one step, or schedule later

🔔 Push Notifications & Reminders

  • Per-schedule push notification toggles
  • Snooze actions directly from notifications (Take Now / Snooze Again)
  • Missed dose catch-up — get a reminder when you open the app after missing a scheduled time
  • Low-supply reminders when inventory drops below threshold
  • Exact alarm support on Android 12+ for reliable delivery after restarts
  • Battery optimization exemption prompt for uninterrupted notifications
  • All reminders auto-restored on app launch

✅ Dose Tracking

  • One-tap dose logging: mark as taken or skipped
  • Undo capability for accidental logs
  • Optimistic UI updates — instant feedback, background sync
  • Calendar view showing daily adherence status (complete / partial / missed)

📊 Reports & Analytics

  • Weekly and monthly adherence charts
  • Streak tracking — consecutive days with full adherence
  • Per-medication missed-dose breakdown
  • Visual bar charts with color-coded adherence levels

🩺 Symptom & Side Effect Tracking

  • Log symptoms with severity (mild / moderate / severe) and optional notes
  • Link symptoms to specific medications or log them independently
  • Browse symptom history by date

👤 User Profile & Account

  • Secure authentication via Supabase (email/password + Google Sign-In)
  • Profile management (name, optional date of birth)
  • At-a-glance stats: medication count, adherence rate, day streak
  • Change password or set a password for OAuth-only accounts
  • Privacy & Security settings with data export and account deletion

👨‍👩‍👧 Caregiver Sharing

  • Share a plain-text medication summary with family or caregivers
  • Choose a time period (7, 30, or 90 days)
  • Summary includes adherence rate, streak, medications, schedules, and supply levels
  • Shared via the system share sheet (messaging, email, etc.)

❓ Help & Support

  • In-app FAQ with expandable answers
  • Direct email link to support
  • Privacy policy link

🧩 Android Home Screen Widget

  • "Next Dose" widget shows your upcoming medication at a glance
  • Tap to open the app directly
  • Auto-updates via a background task handler

🔄 Over-the-Air Updates

  • Automatic OTA updates via expo-updates
  • Error boundary with crash recovery — tap to reload the app after a JS error

📡 Offline Support

  • Network status monitoring with visual offline indicator
  • Graceful handling when connectivity is lost

🌙 Dark Mode

  • Full dark mode support across every screen and component
  • System theme auto-detection
  • Manual toggle in profile settings

📢 Ads (Support the Developer)

  • Non-intrusive banner, interstitial, and app-open ads
  • Granular per-screen ad controls in Ad Preferences
  • UMP consent integration for GDPR compliance
  • All ads can be toggled off individually

🏗️ Architecture

┌─────────────────────────────────────────────────────────┐
│                    Expo Router (Screens)                │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐   │
│  │  Today   │ │   Meds   │ │ Reports  │ │  Profile  │   │
│  └────┬─────┘ └─────┬────┘ └─────┬────┘ └───────┬───┘   │
│       │             │            │              │       │
│  ┌────▼─────────────▼────────────▼──────────────▼────┐  │
│  │              TanStack Query (Server State)        │  │
│  │     useMedications · useSchedules · useDoseLogs   │  │
│  └──────────────────────┬────────────────────────────┘  │
│                         │                               │
│  ┌──────────────────────▼────────────────────────────┐  │
│  │               Supabase (Postgres + RLS)           │  │
│  │     medications · schedules · dose_logs · profiles│  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌───────────────┐  │
│  │ Zustand      │  │ AuthContext  │  │ ThemeContext  │  │
│  │ (Form Drafts)│  │ (Auth+User)  │  │ (Dark Mode)   │  │
│  └──────────────┘  └──────────────┘  └───────────────┘  │
└─────────────────────────────────────────────────────────┘

Tech Stack

Layer Technology Purpose
Framework Expo SDK 55.0.8, React Native 0.83.2 Cross-platform mobile
Routing Expo Router 55.0.7 File-based navigation
Language TypeScript 5.9.3 (strict) Type safety
Server State TanStack Query v5 Data fetching, caching, mutations
Client State Zustand v5 Form draft state for multi-step flows
Auth & DB Supabase Authentication, Postgres, Row-Level Security
OAuth Google Sign-In Social login via @react-native-google-signin
Notifications expo-notifications Push reminders with snooze actions
OTA Updates expo-updates Over-the-air JS bundle updates
Ads Google Mobile Ads Banners, interstitials, app-open ads with UMP consent
Networking NetInfo Offline detection and connectivity monitoring
Widgets react-native-android-widget Android home screen widget
UI React Native + custom components 27 shared UI components
Theming Custom theme system Light/dark mode with system detection
Linter/Formatter Biome 2 Fast, unified linting and formatting
Git Hooks Husky + commitlint Pre-commit checks and conventional commits
Package Manager Bun Fast installs and scripts

Project Structure

medication-tracker/
├── app/                          # Screens (Expo Router file-based routing)
│   ├── _layout.tsx               # Root layout — provider hierarchy
│   ├── index.tsx                 # Welcome / landing screen
│   ├── (tabs)/                   # Tab navigator
│   │   ├── index.tsx             # Today dashboard
│   │   ├── medications.tsx       # Medications list
│   │   ├── reports.tsx           # Reports & analytics
│   │   └── profile.tsx          # User profile & settings menu
│   ├── auth/                     # Authentication screens
│   │   ├── login.tsx
│   │   ├── signup.tsx
│   │   └── profile-setup.tsx
│   ├── medication/               # Medication & scheduling flows
│   │   ├── add.tsx               # Add new medication
│   │   ├── [id].tsx              # Medication detail
│   │   ├── edit.tsx              # Edit medication
│   │   ├── edit-schedule.tsx     # Edit existing schedule
│   │   ├── log-prn.tsx           # Log a PRN (as-needed) dose
│   │   ├── select.tsx            # Select medication to schedule
│   │   ├── schedule.tsx          # Set schedule details
│   │   ├── reminders.tsx         # Configure reminders
│   │   ├── review.tsx            # Review before saving
│   │   └── success.tsx           # Confirmation screen
│   ├── profile/
│   │   └── edit.tsx              # Edit user profile
│   ├── ad-preferences.tsx        # Ad type toggles
│   ├── caregiver-sharing.tsx     # Share medication summary
│   ├── change-password.tsx       # Change password
│   ├── google-callback.tsx       # Google OAuth deep-link handler
│   ├── help-support.tsx          # FAQ & contact
│   ├── log-symptom.tsx           # Log a new symptom
│   ├── notification-settings.tsx # Notification & battery settings
│   ├── notifications.tsx         # Notification history
│   ├── privacy-security.tsx      # Data export, account deletion
│   ├── set-password.tsx          # Set password for OAuth accounts
│   ├── support-developer.tsx     # Ad gallery to support dev
│   └── symptoms.tsx              # Symptom history browser
├── components/ui/                # 27 shared UI components + theme
├── hooks/                        # Custom hooks (queries, theme, calendar, snooze, ads, network)
├── lib/                          # Supabase client, query client, notifications, ads
├── stores/                       # Zustand stores (drafts, ad preferences)
├── types/                        # TypeScript types (database Row/Draft/Update)
├── constants/                    # App constants (days, icons, medications, etc.)
├── utils/                        # Pure utility functions (date, dose, reports, etc.)
├── widgets/                      # Android home screen widget (Next Dose)
├── modules/                      # Native module bridges (widget-bridge)
├── docs/                         # Architecture & system documentation
├── biome.json                    # Biome linter/formatter configuration
├── .editorconfig                 # Editor formatting consistency
├── .commitlintrc.json            # Conventional commit rules
└── .husky/                       # Git hooks (pre-commit, commit-msg)

🗄️ Database Schema

Seven tables with Row-Level Security (RLS) — every query is scoped to the authenticated user. The five core tables are listed below; two legacy tables (inventory, adherence_logs) also exist but are unused. The full schema is defined in supabase/migrations/00000000000000_initial.sql.

── medications ─────────────────────────────────────────
 id              UUID  PK
 user_id         UUID  FK → auth.users
 name            TEXT
 dosage          TEXT
 form            TEXT        -- tablet, capsule, liquid, etc.
 icon            TEXT
 current_supply  INTEGER
 low_supply_threshold INTEGER
 is_prn          BOOLEAN     -- true = "as needed" (no fixed schedule)
 rxcui           TEXT        -- RxNorm concept ID (optional, from drug search)
 generic_name    TEXT        -- generic drug name (optional, from drug search)
 is_active       BOOLEAN     -- soft delete
 created_at      TIMESTAMPTZ
 updated_at      TIMESTAMPTZ

── schedules ───────────────────────────────────────────
 id              UUID  PK
 medication_id   UUID  FK → medications
 user_id         UUID  FK → auth.users
 frequency       TEXT        -- Daily, Specific Days, Interval
 selected_days   TEXT[]      -- ['Mon', 'Wed', 'Fri']
 times_of_day    TEXT[]      -- ['Morning', 'Evening']
 interval_days   INTEGER     -- every N days (nullable, for interval frequency)
 dosage_per_dose INTEGER
 push_notifications BOOLEAN
 sms_alerts      BOOLEAN
 snooze_duration TEXT        -- '5 min', '15 min', etc.
 instructions    TEXT
 start_date      DATE
 end_date        DATE        -- NULL = continue forever
 is_active       BOOLEAN     -- soft delete
 created_at      TIMESTAMPTZ
 updated_at      TIMESTAMPTZ

── dose_logs ───────────────────────────────────────────
 id              UUID  PK
 schedule_id     UUID  FK → schedules  (NULL for PRN doses)
 medication_id   UUID  FK → medications
 user_id         UUID  FK → auth.users
 scheduled_date  DATE
 time_label      TEXT        -- 'Morning', '08:30', etc.
 status          TEXT        -- 'taken' | 'skipped'
 reason          TEXT        -- optional reason (PRN doses)
 logged_at       TIMESTAMPTZ
 created_at      TIMESTAMPTZ
 UNIQUE (schedule_id, scheduled_date, time_label)

── symptoms ────────────────────────────────────────────
 id              UUID  PK
 user_id         UUID  FK → auth.users
 medication_id   UUID  FK → medications  (NULL if unlinked)
 name            TEXT        -- e.g. 'Headache', 'Nausea'
 severity        TEXT        -- 'mild' | 'moderate' | 'severe'
 notes           TEXT
 logged_at       TIMESTAMPTZ
 logged_date     DATE
 created_at      TIMESTAMPTZ

── profiles ────────────────────────────────────────────
 id              UUID  PK  = auth.uid()
 full_name       TEXT
 age             INTEGER     -- optional
 date_of_birth   DATE        -- optional
 updated_at      TIMESTAMPTZ

🚀 Getting Started

Prerequisites

1. Clone the repository

git clone https://github.com/PanagiotisKaraliolios/medication-tracker.git
cd medication-tracker

2. Install dependencies

bun install

3. Configure environment variables

Create a .env file in the project root:

EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_KEY=your-anon-public-key

Get these from your Supabase project dashboard → Settings → API.

4. Set up the database

Run supabase/migrations/00000000000000_initial.sql in the Supabase SQL Editor (Dashboard → SQL Editor → New Query). This single migration creates all tables, indexes, and RLS policies.

5. Configure Google Sign-In (optional)

  1. Create an OAuth 2.0 Web Client ID in Google Cloud Console
  2. Add the web client ID to your Supabase project (Authentication → Providers → Google)
  3. Update webClientId in hooks/useGoogleAuth.ts

6. Configure Ads (optional)

  1. Create an AdMob account and register your app
  2. Update the ad unit IDs in lib/ads.ts
  3. Add your AdMob app ID to app.json under the react-native-google-mobile-ads plugin

7. Start the development server

bun run start

Scan the QR code with Expo Go, or press:

  • a — open on Android emulator
  • i — open on iOS simulator
  • w — open in web browser

Building for device

For push notifications, Google Sign-In, ads, and full native functionality, create a development build:

bun run prebuild
bun run android   # or: bun run ios

📁 Key Files Reference

File Purpose
hooks/useQueryHooks.ts All TanStack Query/mutation hooks
hooks/useGoogleAuth.ts Google Sign-In integration hook
hooks/useNetworkStatus.ts Online/offline connectivity monitoring
hooks/useDrugSearch.ts RxNorm drug database search with debounce
hooks/useAppOpenAd.ts App-open ad loading and display
hooks/useBatteryOptimization.ts Android battery optimization exemption prompt
stores/draftStores.ts Zustand stores for medication & schedule drafts
stores/adPreferencesStore.ts Zustand store for per-screen ad toggles
lib/queryClient.ts Query client singleton (staleTime, gcTime, focus)
lib/queryKeys.ts Centralised query key factory for cache invalidation
lib/notifications.ts Push notification scheduling, snooze actions, low-supply alerts
lib/ads.ts Ad unit IDs and configuration
lib/interstitialManager.ts Interstitial ad preloading and frequency capping
lib/supabase.ts Supabase client singleton
lib/widgetBridge.tsx Bridge for Android home screen widget data
types/database.ts All TypeScript types (Row, Draft, Update) + empty defaults
contexts/AuthContext.tsx Auth state, session management, profile loading
contexts/ThemeContext.tsx Theme preference with AsyncStorage persistence
components/ui/theme.ts Color schemes, gradients, shadows, border radii
components/ui/ErrorBoundary.tsx App-wide error boundary with crash recovery
docs/architecture.md Detailed architecture documentation

🧩 State Management

Concern Solution Location
Server data (medications, schedules, dose logs) TanStack Query v5 hooks/useQueryHooks.ts
Form drafts (multi-step creation flows) Zustand v5 stores/draftStores.ts
Ad preferences (per-screen ad toggles) Zustand v5 stores/adPreferencesStore.ts
Authentication (session, user, profile) React Context contexts/AuthContext.tsx
Theme (light / dark / system) React Context contexts/ThemeContext.tsx

There is no MedicationContext or Redux. Screens consume data exclusively through TanStack Query hooks and never call supabase.from() directly for medications, schedules, or dose logs.


🎨 Theming

Every component supports light and dark mode:

const c = useThemeColors();                        // Get current color scheme
const styles = useMemo(() => makeStyles(c), [c]);  // Memoize styles

// At bottom of file:
function makeStyles(c: ColorScheme) {
  return StyleSheet.create({
    container: { flex: 1, backgroundColor: c.background },
    card: { backgroundColor: c.card, ...shadows.sm, borderRadius: borderRadius.lg },
  });
}

📜 Scripts

Command Description
bun run start Start Expo dev server
bun run start:tunnel Start with tunnel (for physical devices on different networks)
bun run prebuild Generate native projects (clean)
bun run android Prebuild + run on Android
bun run ios Prebuild + run on iOS
bun run web Start for web
bun run typecheck Run TypeScript type checking
bun run lint Lint all files with Biome
bun run lint:fix Lint and auto-fix with Biome
bun run format Format all files with Biome
bun run check Lint + format + organize imports (Biome)

🛠️ Built With


🔧 Code Quality & Tooling

Tool Purpose Config
Biome Linting + formatting (replaces ESLint + Prettier) biome.json
Husky Git hooks — runs lint & tests on pre-commit .husky/pre-commit
commitlint Enforces Conventional Commits .commitlintrc.json
EditorConfig Consistent formatting across editors .editorconfig
TypeScript Strict mode type checking tsconfig.json

Commit Convention

All commits follow the Conventional Commits spec, enforced by commitlint + Husky:

feat(auth): add Google Sign-In
fix(schedule): correct interval calculation
docs: update README

Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert.


📄 License

This project is private and not licensed for public use.


Made with ❤️ using Expo & React Native

About

A mobile medication tracking app built with Expo and React Native. Track medications, set reminders, log doses, monitor adherence, and manage supply — powered by Supabase and TanStack Query.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages