# Project export: Hero

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2026
- Tagline: You could save a life.
- Devpost: https://devpost.com/software/organmatch
- GitHub: https://github.com/angelinawwu/treehacks26
- Video: https://www.youtube.com/embed/K8HsTLNOgJI?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 2 GitHub contributor(s) — angelinawwu (23 commits), abao27 (3 commits)

## Devpost submission (written by the team)

### Inspiration

At the time of writing this, the United Network for Organ Sharing (UNOS) reports there are 108,562 people on the national transplant list. Additionally, the NIH reports that 17 people die waiting for an organ each day. This means that throughout the mere duration of this hackathon, approximately 26 people died awaiting an organ in the U.S and nearly 240 new names were added (Penn Medicine). This unfortunate reality is not due to the inevitability of death but the scarcity of organs: a scarcity that can be greatly reduced by increasing the number of registered donors and living donors. This project was largely inspired by the Nobel Prize winning economic research by Al Roth and Judd Kessler that encourages donor registration through a priority policy for people that were already organ donors. By rewarding those willing to make a scarce resource available, implementation in Israel and Singapore saw a dramatic increase in registration rates and living donor donation. The current U.S. organ registration system not only fails to implement this policy but remains outdated with its current registration system. Current organ registration is largely relegated to checking a box when getting your driver’s license, completely excluding those who don’t have a driver’s license (I’m working on it). Nevertheless, such a system fails to reflect the life determining severity of maximizing the number of organ donors.

### What it does

Our app, Hero, makes registering to be an organ donor easier and implements the aforementioned policy by alerting you once you hit the 3-year mark as an organ donor where you receive a level of priority on the UNOS donor list if you ever (hopefully never) need an organ. If you're “willing to spare” and eligible it uses the stable matching algorithm to match you with possible recipients and once you pick a match and a timeline sends the information to a hospital to schedule surgery. After donation, you are given the highest level of priority that can be passed off to a loved one waiting for an organ. Granted, sacrificing an organ is the only way you can contribute to the health of others, Hero given a zip code finds close by blood donation centers for you to donate blood. When it comes to illness, we are too often left powerless in protecting those we love most from suffering, Hero's easier donor registration and organ donor matching allows us to indirectly help those we love by directly helping those others love.

### How we built it

We built Hero as a mobile app using React Native and Expo SDK 54 with TypeScript. Navigation is handled by Expo Router (file-based routing), while we used NativeWind (Tailwind CSS for React Native) for styling to keep UI development fast and consistent. The matching algorithm was originally prototyped in Python, then ported entirely to TypeScript. It scores recipients using blood type compatibility, medical priority factors (waiting time, sensitization, age, eGFR), and geographic proximity (converting zip codes to coordinates via the zipcodes package and applying Haversine distance). Eligibility screening cross-references user responses against a rules table derived from real donor disqualification criteria. We integrated the Overpass API/OpenStreetMap to query for nearby blood donation centers and blood banks based on the user's zip code, giving real geographic results without needing API keys. Encryption uses AES-256-GCM via the Web Crypto API, ported from our Python reference implementation. The app runs entirely frontend-side with in-memory auth and mock patient records, but would include a comprehensive backend database in a real-world application.

### Challenges we ran into

: Design to dev: Converting a Figma design file into code with intuitive layout for multiple screen sizes Python → TypeScript: Porting the matching logic and AES-256-GCM encryption while keeping behavior identical Frontend-only setup: Deciding where to put auth, API calls, and matching when there’s no backend Accomplishments we're proud of: Encryption: Successfully implementing HIPAA-compliant encryption of data! App development: Creating our very first mobile app with React Native Intuitive UI: Combining design with development to create an app that feels human-first and accessible User flow: Onboarding, eligibility screening, matching, scheduling, and thank-you screen connected end-to-end Live blood drives: OpenStreetMap API integration to show real donation sites by zip code, no API key required Domain-aware matching: Matching based on blood type, recipient priority, and geographic distance.

### What we learned

When designing for healthcare, the importance of erring on the side of caution instead of leaving things to chance. When determining matching, we had to make sure the questionnaire was exhaustive and learned to be quick to disqualify potential donors, sacrificing donor match maximization to ensure the safety and compatibility of all matches. None of us had extensive hackathon experience or had ever developed a mobile app before, so this was a huge and exciting learning experience. We learned a lot about the thought behind design decisions and how to collaborate on moving parts to ensure a working product.

### What's next

We’re aware that ultimately the success of our application relies on policy reform; however, we thought Treehacks ( i.e.“boiling the ocean” ) called for innovation that transcended outdated and negligent infrastructure. Regardless, with improvements on the encryption logic to ensure user privacy, optimized weighting for matching and connection to national health organizations, Hero can hopefully evolve to facilitate plasma and liver donation through matching as well. In addition to allowing both hospitals and users quick access to their donor status. We hope the development of this application will trigger a much needed reform of NOTA and UAGA laws along with making registration for organ donors more accessible. Our team is sure that, Hero, policy allowing, revolutionizes organ donation and would undoubtedly save countless lives as seen in other countries. Not to mention, facilitating generosity and challenging the way we think about our own mortality.

## README (from the GitHub repository)

# Hero

Save lives. Be a hero.

A human-first mobile app for organ donation.

## Overview

Hero helps users register as organ donors, track their donor status, and explore living kidney/liver donation. The app includes:

- **Onboarding & account creation** — Profile setup with medical info, security questions, and authentication
- **Donor dashboard** — Status tracker, blood drive finder, and living donation CTA
- **Living donor path** — Education, eligibility screening (5-part questionnaire), and preference setting for directed vs. altruistic donation
- **Potential matches** — Compatibility-based recipient matching

The project uses a frontend-only architecture with mock data and in-memory auth. Encryption (AES-256-GCM) and matching logic are implemented in TypeScript within the frontend.

## Tech Stack

- **React Native** + **Expo** (SDK 54)
- **Expo Router** — File-based navigation
- **NativeWind / Tailwind CSS** — Utility-first styling
- **TypeScript**
- **Phosphor Icons**
- Fonts: Inria Serif, Archivo, Geist Mono

## Project Structure

```
treehacks26/
├── frontend/               # Expo/React Native app
│   ├── app/
│   │   ├── (auth)/         # Welcome, Login, Medical Info, Affirmation
│   │   └── (tabs)/         # Home, Donate, Profile
│   ├── components/
│   ├── constants/
│   ├── contexts/           # AuthContext (in-memory user state)
│   └── services/           # API, encryption, records, mockData
├── backend/                # Reference implementations (Python)
│   ├── encrypt/            # AES-256-GCM encryption (Python)
│   ├── sm_alg/             # Priority/matching logic
│   └── records.json
└── README.md
```

## Getting Started

### Prerequisites

- Node.js (v18+)
- npm or yarn
- Xcode (for iOS) or Android Studio (for Android)
- Expo Go app (optional, for physical device testing)

### Installation

1. Clone the repo and install dependencies:

```bash
cd frontend
npm install
```

2. Start the development server:

```bash
npm start
```

3. Run on a platform:

- **iOS simulator**: Press `i` in the terminal, or run `npm run ios`
- **Android emulator**: Press `a` in the terminal, or run `npm run android`
- **Web**: Press `w` in the terminal, or run `npm run web`
- **Physical device**: Scan the QR code with Expo Go

## Features

### Authentication (Frontend-Only)

- **Register** — Create account with first name, last name, birthday, gender, blood type, SSN, security question, and password
- **Login** — Sign in with first name, last name, and password
- Data is kept in memory only (no persistence) — suitable for demos and prototyping

### Eligibility Screening

A 5-part questionnaire covering:

1. Health conditions (kidney disease, diabetes, blood pressure, cancer, surgeries, heart disease)
2. Other conditions (liver, autoimmune, blood disorders, lung, neurological, psychiatric)
3. Infections & family history
4. Lifestyle (smoking, alcohol, drugs, medications, pregnancy)
5. Risk factors (incarceration, sexual behavior, needle sharing, travel, etc.)

Each question supports Yes, No, and Don't know.

### Living Donation Flow

1. **Education** — Information on living kidney donation and laparoscopic surgery
2. **Screening** — Complete the eligibility questionnaire
3. **Preferences** — Choose to donate to a specific person or altruistically
4. **Matches** — View potential recipients with compatibility scores

## Backend Reference

The `backend/` folder contains Python implementations used as reference:

- **encrypt/** — AES-256-GCM encryption (ported to TypeScript in `frontend/services/encryption.ts`)
- **sm_alg/** — Priority scoring and matching logic
- **records.json** — Sample recipient and donor records (ported to `frontend/services/recordsData.ts`)

## License

Private — TreeHacks 2026


## Detected evidence (automated analysis)

Indexed codebase: 64 recognized source files, 201 KB.
- CSS (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (77 of 77)

```
.gitignore
backend/.file.swp
backend/encrypt/decrypt.py
backend/encrypt/encrypt.py
backend/encrypt/requirements.txt
backend/records.json
backend/sm_alg/logic.ts
backend/sm_alg/matching.ts
backend/sm_alg/simulation.ts
backend/sm_alg/types.ts
frontend/.gitignore
frontend/.vscode/extensions.json
frontend/.vscode/settings.json
frontend/app.json
frontend/app/_layout.tsx
frontend/app/(auth)/_layout.tsx
frontend/app/(auth)/affirmation.tsx
frontend/app/(auth)/login.tsx
frontend/app/(auth)/medical-info.tsx
frontend/app/(auth)/welcome.tsx
frontend/app/(tabs)/_layout.tsx
frontend/app/(tabs)/donate.tsx
frontend/app/(tabs)/index.tsx
frontend/app/(tabs)/profile.tsx
frontend/app/blood-drives.tsx
frontend/app/donor-ineligible.tsx
frontend/app/donor-questionnaire.tsx
frontend/app/donor-result.tsx
frontend/app/donor-schedule.tsx
frontend/app/donor-thank-you.tsx
frontend/app/modal.tsx
frontend/app/profile-medical-profile.tsx
frontend/app/profile-notifications.tsx
frontend/app/profile-personal-info.tsx
frontend/app/profile-privacy-security.tsx
frontend/app/share-impact.tsx
frontend/babel.config.js
frontend/components/Button.tsx
frontend/components/Card.tsx
frontend/components/external-link.tsx
frontend/components/haptic-tab.tsx
frontend/components/hello-wave.tsx
frontend/components/parallax-scroll-view.tsx
frontend/components/ProgressBar.tsx
frontend/components/themed-text.tsx
frontend/components/themed-view.tsx
frontend/components/ui/collapsible.tsx
frontend/components/ui/icon-symbol.ios.tsx
frontend/components/ui/icon-symbol.tsx
frontend/constants/eligibilityQuestions.ts
frontend/constants/theme.ts
frontend/contexts/AuthContext.tsx
frontend/eligibilityQs.txt
frontend/eslint.config.js
frontend/global.css
frontend/hooks/use-color-scheme.ts
frontend/hooks/use-color-scheme.web.ts
frontend/hooks/use-theme-color.ts
frontend/ineligible.csv
frontend/metro.config.js
frontend/nativewind-env.d.ts
frontend/package.json
frontend/README.md
frontend/scripts/reset-project.js
frontend/services/api.ts
frontend/services/bloodDrives.ts
frontend/services/encryption.ts
frontend/services/matching.ts
frontend/services/mockData.ts
frontend/services/records.ts
frontend/services/recordsData.ts
frontend/tailwind.config.js
frontend/tsconfig.json
package.json
README.md
test_logic.js
userflow.md
```

### Dependencies

- backend/encrypt/requirements.txt: pip@freeze > requirements.txt
- frontend/package.json: @expo-google-fonts/archivo@^0.4.2, @expo-google-fonts/geist-mono@^0.4.1, @expo-google-fonts/inria-serif@^0.4.1, @expo/vector-icons@^15.0.3, @react-navigation/bottom-tabs@^7.4.0, @react-navigation/elements@^2.6.3, @react-navigation/native@^7.1.8, @types/react@~19.1.0, @types/zipcodes@^8.0.5, eslint@^9.25.0, eslint-config-expo@~10.0.0, expo@~54.0.33, expo-constants@~18.0.13, expo-font@~14.0.11, expo-haptics@~15.0.8, expo-image@~3.0.11, expo-linking@~8.0.11, expo-router@~6.0.23, expo-splash-screen@~31.0.13, expo-status-bar@~3.0.9, expo-symbols@~1.0.8, expo-system-ui@~6.0.9, expo-web-browser@~15.0.10, nativewind@^4.2.1, phosphor-react-native@^3.0.3, react@19.1.0, react-dom@19.1.0, react-native@0.81.5, react-native-gesture-handler@~2.28.0, react-native-reanimated@~4.1.1, react-native-safe-area-context@~5.6.0, react-native-screens@~4.16.0, react-native-web@~0.21.0, react-native-worklets@0.5.1, tailwindcss@^3.4.19, typescript@~5.9.2, zipcodes@^8.0.0
- package.json: phosphor-react-native@^3.0.3

### Recent commits (newest first)

- cleanup
- capitalization
- mb
- homepage
- tabs in profile and other stuff
- styling and things
- archivo font weights
- blood drive
- selection, scheduling
- location matching
- ALGO
- donor questionnaire pipeline
- we can't say that
- readme
- user auth, mock
- Merge branch 'main' of https://github.com/angelinawwu/treehacks26
- change to csv and fix formats
- Merge branch 'main' of https://github.com/angelinawwu/treehacks26
- h
- ineligible responses

## Key source files (fetched from GitHub, selected and truncated for size)

### userflow.md

```markdown
Organ Scarcity Solution: Primary User Flow
1. Onboarding & Verification
Sign-up: User creates a single-account profile (addressing your "one account" research point).

Medical Data Entry: Input blood type and demographic info.

Identity Sync: Connect with hospital/ID records to verify current donor status.

The "Affirmation": User confirms or updates their donor status for the current year.

2. The Donor Dashboard
Status Tracker: Displays "Member Status" (e.g., Bronze, Silver, Gold based on years of being a registered donor).

Action Center:

Find Local Blood Drives: Map view of nearby locations.

"Willing to Spare?": A specialized CTA for living kidney/liver donation.

3. Living Donor Path (The "Matching System")
If the user selects "Willing to Spare," the flow becomes a high-stakes vetting process:

Education Phase: Information on surgery implications, recovery timelines, and hospital coordination.

Compatibility Screening: Detailed questionnaire to determine what might eliminate them as a donor.

Preference Setting: * Option to designate "Highest Priority" to close kin.

Option to enter a Swap Program (If I donor to a stranger, my kin moves up the list).

4. The Matching Engine (Backend Logic)
Once a user is verified and compatible, the algorithm (Al Roth/Graph Theory inspired) takes over:

Direct Match Search: Finds a proximal match on the waitlist.

Cycle Detection (2-way/3-way swaps): If a direct match for a loved one isn't found, the system looks for "chains" where Donor A gives to Recipient B, and Donor B gives to Recipient A.

Post-Surgery Priority: System automatically updates the donor’s profile to "High Priority" status for future needs, as a "thank you" for their living donation.
```

### package.json

```
{
  "dependencies": {
    "phosphor-react-native": "^3.0.3"
  }
}

```

### frontend/package.json

```
{
  "name": "frontend",
  "main": "expo-router/entry",
  "version": "1.0.0",
  "scripts": {
    "start": "expo start",
    "reset-project": "node ./scripts/reset-project.js",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "lint": "expo lint"
  },
  "dependencies": {
    "@expo-google-fonts/archivo": "^0.4.2",
    "@expo-google-fonts/geist-mono": "^0.4.1",
    "@expo-google-fonts/inria-serif": "^0.4.1",
    "@expo/vector-icons": "^15.0.3",
    "@react-navigation/bottom-tabs": "^7.4.0",
    "@react-navigation/elements": "^2.6.3",
    "@react-navigation/native": "^7.1.8",
    "expo": "~54.0.33",
    "expo-constants": "~18.0.13",
    "expo-font": "~14.0.11",
    "expo-haptics": "~15.0.8",
    "expo-image": "~3.0.11",
    "expo-linking": "~8.0.11",
    "expo-router": "~6.0.23",
    "expo-splash-screen": "~31.0.13",
    "expo-status-bar": "~3.0.9",
    "expo-symbols": "~1.0.8",
    "expo-system-ui": "~6.0.9",
    "expo-web-browser": "~15.0.10",
    "nativewind": "^4.2.1",
    "phosphor-react-native": "^3.0.3",
    "react": "19.1.0",
    "react-dom": "19.1.0",
    "react-native": "0.81.5",
    "react-native-gesture-handler": "~2.28.0",
    "react-native-reanimated": "~4.1.1",
    "react-native-safe-area-context": "~5.6.0",
    "react-native-screens": "~4.16.0",
    "react-native-web": "~0.21.0",
    "react-native-worklets": "0.5.1",
    "tailwindcss": "^3.4.19",
    "zipcodes": "^8.0.0"
  },
  "devDependencies": {
    "@types/react": "~19.1.0",
    "@types/zipcodes": "^8.0.5",
    "eslint": "^9.25.0",
    "eslint-config-expo": "~10.0.0",
    "typescript": "~5.9.2"
  },
  "private": true
}

```

### backend/encrypt/requirements.txt

```
pip freeze > requirements.txt

```

### frontend/app/_layout.tsx

```typescript
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import 'react-native-reanimated';
import '../global.css';
import { useFonts, InriaSerif_400Regular } from '@expo-google-fonts/inria-serif';
import { Archivo_300Light, Archivo_400Regular } from '@expo-google-fonts/archivo';
import { GeistMono_300Light } from '@expo-google-fonts/geist-mono';

import { useColorScheme } from '@/hooks/use-color-scheme';
import { Colors } from '../constants/theme';
import { useEffect } from 'react';
import * as SplashScreen from 'expo-splash-screen';
import { AuthProvider } from '../contexts/AuthContext';

SplashScreen.preventAutoHideAsync();

export const unstable_settings = {
  // Ensure any route can link back to first page of initial stack
  initialRouteName: '(auth)',
};

export default function RootLayout() {
  const colorScheme = useColorScheme();
  const [loaded] = useFonts({
    InriaSerif_400Regular,
    Archivo_300Light,
    Archivo_400Regular,
    GeistMono_300Light,
  });

  useEffect(() => {
    if (loaded) {
      SplashScreen.hideAsync();
    }
  }, [loaded]);

  if (!loaded) {
    return null;
  }

  return (
    <AuthProvider>
      <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
        <Stack screenOptions={{ headerShown: false }}>
          <Stack.Screen name="(auth)" options={{ headerShown: false }} />
          <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
          <Stack.Screen name="donor-questionnaire" options={{ headerShown: false }} />
          <Stack.Screen name="donor-result" options={{ headerShown: false }} />
          <Stack.Screen name="donor-ineligible" options={{ headerShown: false }} />
          <Stack.Screen name="donor-schedule" options={{ headerShown: false }} />
          <Stack.Screen name="donor-thank-you" options={{ headerShown: false }} />
          <Stack.Screen name="blood-drives" options={{ headerShown: false }} />
          <Stack.Screen name="share-impact" options={{ headerShown: false }} />
          <Stack.Screen name="profile-personal-info" options={{ headerShown: false }} />
          <Stack.Screen name="profile-medical-profile" options={{ headerShown: false }} />
          <Stack.Screen name="profile-notifications" options={{ headerShown: false }} />
          <Stack.Screen name="profile-privacy-security" options={{ headerShown: false }} />
          <Stack.Screen name="modal" options={{ presentation: 'modal', title: 'Modal' }} />
        </Stack>
        <StatusBar style="auto" />
      </ThemeProvider>
    </AuthProvider>
  );
}

```

### frontend/app/(auth)/_layout.tsx

```typescript
import { Stack } from 'expo-router';
import { Colors } from '../../constants/theme';

export default function AuthLayout() {
  return (
    <Stack
      screenOptions={{
        headerShown: false,
        contentStyle: { backgroundColor: Colors.light.background },
      }}
    >
      <Stack.Screen name="welcome" />
      <Stack.Screen name="login" />
      <Stack.Screen name="medical-info" />
      <Stack.Screen name="affirmation" />
    </Stack>
  );
}

```

### frontend/app/(tabs)/_layout.tsx

```typescript
import React from 'react';
import { House, Heart, User } from 'phosphor-react-native';
import { Tabs } from 'expo-router';

import { Colors } from '../../constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme';

export default function TabLayout() {
  const colorScheme = useColorScheme();

  return (
    <Tabs
      screenOptions={{
        tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
        headerShown: false,
        tabBarStyle: {
          backgroundColor: '#FCFAF8',
          borderTopColor: '#CCCCCC',
        },
      }}>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Home',
          tabBarIcon: ({ color }) => <House size={28} color={color} style={{ marginBottom: -3 }} />,
        }}
      />
      <Tabs.Screen
        name="donate"
        options={{
          title: 'Donate',
          tabBarIcon: ({ color }) => <Heart size={28} color={color} style={{ marginBottom: -3 }} />,
        }}
      />
      <Tabs.Screen
        name="profile"
        options={{
          title: 'Profile',
          tabBarIcon: ({ color }) => <User size={28} color={color} style={{ marginBottom: -3 }} />,
        }}
      />
    </Tabs>
  );
}

```

### frontend/app/(tabs)/index.tsx

```typescript
import React, { useEffect, useState } from 'react';
import { View, Text, ScrollView, SafeAreaView, RefreshControl, TouchableOpacity } from 'react-native';
import { router } from 'expo-router';
import { Card } from '../../components/Card';
import { Button } from '../../components/Button';
import { api } from '../../services/api';
import { MapPin, HandHeart } from 'phosphor-react-native';
import { ProgressBar } from '../../components/ProgressBar';
import { useAuth } from '../../contexts/AuthContext';

const MILESTONE_YEARS = 3;

function formatDonorDuration(yearsRegistered: number): string {
  const totalMonths = Math.round(yearsRegistered * 12);
  const years = Math.floor(totalMonths / 12);
  const months = totalMonths % 12;
  if (years > 0 && months > 0) return `${years} years, ${months} months.`;
  if (years > 0) return `${years} ${years === 1 ? 'year' : 'years'}.`;
  return `${months} ${months === 1 ? 'month' : 'months'}.`;
}

function getProgressToMilestone(yearsRegistered: number): number {
  return Math.min(yearsRegistered / MILESTONE_YEARS, 1);
}

function formatMonthsRemaining(yearsRegistered: number): string {
  const monthsRemaining = Math.max(0, Math.ceil((MILESTONE_YEARS - yearsRegistered) * 12));
  if (monthsRemaining === 0) return '0';
  return `${monthsRemaining} ${monthsRemaining === 1 ? 'MONTH' : 'MONTHS'}`;
}

export default function DashboardScreen() {
  const { user: authUser } = useAuth();
  const [user, setUser] = useState<any>(null);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);

  const loadData = async () => {
    try {
      const userData = await api.getUserProfile();
      setUser(userData);
    } catch (error) {
      console.error('Failed to load user data', error);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  };

  useEffect(() => {
    loadData();
  }, []);

  const onRefresh = () => {
    setRefreshing(true);
    loadData();
  };

  if (loading) {
    return (
      <View className="flex-1 justify-center items-center">
        <Text>Loading...</Text>
      </View>
    );
  }

  return (
    <SafeAreaView className="flex-1 bg-background">
      <ScrollView
        contentContainerStyle={{ padding: 24 }}
        refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
      >
        <Text className="text-4xl font-serif text-text mb-6">
          Hello, {authUser?.firstName ?? user?.name?.split(' ')[0] ?? ''}.
        </Text>

        <View className="bg-surface rounded-[20px] p-6 mb-8">
          <Text className="text-2xl font-serif text-text mb-2">Willing to spare?</Text>
          <Text className="text-base font-sans text-text-secondary leading-5 mb-5">
            Living donation is a profound way to save a life now. Learn more about kidney and liver donation.
          </Text>
          <Button
            title="Explore living donation"
            onPress={() => router.push('/donate')}
            style="rounded-xl py-3.5"
            textStyle="font-sans-medium text-base"
          />
        </View>

        <View className="mb-10">
          <Text className="text-xs font-mono text-text-secondary tracking-wide mb-2 uppercase">
            YOU'VE BEEN A DONOR FOR
          </Text>
          <Text className="text-3xl font-serif text-text mb-3">
            {formatDonorDuration(user?.yearsRegistered ?? 0)}
          </Text>
          <Text className="text-base font-sans text-text-secondary leading-5 mb-4">
            Three-year donors receive organ transplant priority for themselves and their families.
          </Text>
          <View className="mb-2 bg-surface-alt rounded overflow-hidden">
            <ProgressBar progress={getProgressToMilestone(user?.yearsRegistered ?? 0)} color="#79A7C2" height={8} />
          </View>
          <Text className="text-xs font-mono text-text-secondary tracking-wide uppercase">
            {formatMonthsRemaining(user?.yearsRegistered ?? 0)} REMAINING
          </Text>
        </View>

        <Text className="text-2xl font-serif text-text mb-2">Action Center</Text>

        <View className="flex-row gap-4">
          <TouchableOpacity
            onPress={() => router.push('/blood-drives')}
            className="flex-1 bg-surface rounded-[20px] p-5 h-auto justify-between"
            activeOpacity={0.8}
          >
            <View className="mb-3"><MapPin size={24} color="#E77664" /></View>
            <Text className="text-xl font-serif text-text mb-1 leading-6">Got blood?</Text>
            <Text className="text-sm font-sans text-text-secondary leading-[18px]">
              Locate blood drives near you. 
            </Text>
          </TouchableOpacity>

          <TouchableOpacity
            onPress={() => router.push('/share-impact')}
            className="flex-1 bg-surface rounded-[20px] p-5 h-auto justify-between"
            activeOpacity={0.8}
          >
            <View className="mb-3"><HandHeart size={24} color="#79A7C2" /></View>
            <Text className="text-xl font-serif text-text mb-1 leading-6">Share impact</Text>
            <Text className="text-sm font-sans text-text-secondary leading-[18px]">
              Spread awareness with friends.
            </Text>
          </TouchableOpacity>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}

```

### test_logic.js

```javascript
// // --- THE LOGIC ---
// const calculatePriorityScore = (patient) => {
//     let score = 0;
//     score += patient.yearsWaiting; 
//     if (patient.cpra >= 98) score += 50;
//     if (patient.driversLicense.endsWith('D')) score += 10; 
//     return score;
// };

// const isBloodCompatible = (donor, recipient) => {
//     const map = { 'O': ['O', 'A', 'B', 'AB'], 'A': ['A', 'AB'], 'B': ['B', 'AB'], 'AB': ['AB'] };
//     return map[donor].includes(recipient);
// };

// // --- THE DATA ---
// const patients = [
//     { name: 'Mike', bloodType: 'A', yearsWaiting: 10, cpra: 10, driversLicense: '123' },
//     { name: 'Sarah', bloodType: 'A', yearsWaiting: 2, cpra: 10, driversLicense: '987D' }
// ];
// const donor = { name: 'Donor1', bloodType: 'A' };

// // --- THE RUN ---
// console.log("🔹 RUNNING LOGIC TEST 🔹");

// const results = patients.map(p => ({
//     name: p.name,
//     score: calculatePriorityScore(p)
// }));

// console.log("Scores:", results);

// const winner = patients
//     .filter(p => isBloodCompatible(donor.bloodType, p.bloodType))
//     .sort((a, b) => calculatePriorityScore(b) - calculatePriorityScore(a))[0];

// console.log("🎉 WINNER:", winner.name);

// --- 1. THE BRAIN (The Logic) ---

const calculateAge = (dob) => {
    const diff = Date.now() - new Date(dob).getTime();
    return Math.floor(diff / (1000 * 60 * 60 * 24 * 365.25));
};

const calculateScore = (p) => {
    let score = 0;
    
    // Rule A: Waiting Time (1 pt per year)
    score += p.yearsWaiting;

    // Rule B: Pediatric Bonus (Children < 18 get +15 pts)
    const age = calculateAge(p.dob);
    if (age < 18) score += 15;

    // Rule C: The "Israeli Twist" (Donor Card 'D' suffix gets +10 pts)
    if (p.driversLicense.endsWith('D')) score += 10;

    // Rule D: Sickness Bonus (CPRA > 90% gets +20 pts)
    if (p.cpra > 90) score += 20;

    return { total: score, age: age };
};

const isCompatible = (donorBT, patientBT) => {
    const map = { 
        'O': ['O', 'A', 'B', 'AB'], 
        'A': ['A', 'AB'], 
        'B': ['B', 'AB'], 
        'AB': ['AB'] 
    };
    return map[donorBT].includes(patientBT);
};

// --- 2. THE TEST DATA (Diverse Scenarios) ---

const waitlist = [
    { name: "Old Joe", dob: "1955-05-10", bloodType: "A", yearsWaiting: 15, cpra: 10, driversLicense: "XYZ123" },
    { name: "Young Sarah", dob: "1995-02-20", bloodType: "A", yearsWaiting: 2, cpra: 10, driversLicense: "ABC987D" },
    { name: "Little Timmy", dob: "2018-11-30", bloodType: "B", yearsWaiting: 1, cpra: 5, driversLicense: "KID001" },
    { name: "Sick Sam", dob: "1985-08-15", bloodType: "A", yearsWaiting: 3, cpra: 99, driversLicense: "MED444" },
    { name: "Universal Recipient", dob: "1990-01-01", bloodType: "AB", yearsWaiting: 1, cpra: 0, driversLicense: "UNIV" }
];

// --- 3. THE SIMULATOR ENGINE ---

function runSimulation(donorName, donorBT) {
    console.log(`\n=== DONOR APPEARED: ${donorName} (Type ${donorBT}) ===`);

    // 1. Filter by Blood Compatibility
    const candidates = waitlist.filter(p => isCompatible(donorBT, p.bloodType));
    
    // 2. Score them
    const scoredCandidates = candidates.map(p => {
        const result = calculateScore(p);
        return { ...p, score: result.total, calculatedAge: result.age };
    });

    // 3. Sort by Score (High to Low)
    scoredCandidates.sort((a, b) => b.score - a.score);

    // 4. Print Table
    console.table(scoredCandidates.map(c => ({
        Name: c.name,
        Age: c.calculatedAge,
        Wait: c.yearsWaiting,
        "Donor Card?": c.driversLicense.endsWith('D') ? "YES" : "NO",
        Score: c.score,
        Compatible: "YES"
    })));

    if (scoredCandidates.length > 0) {
        console.log(`🏆 MATCH FOUND: ${scoredCandidates[0].name} receives the kidney!`);
    } else {
        console.log("❌ NO MATCH: No compatible blood types on list.");
    }
}

// --- 4. EXECUTE SCENARIOS ---

console.log("🚀 STARTING ORGAN TRANSPLANT SIMULATION");

// Scenario 1: A Type A Donor (Tests Sarah's Bonus vs Joe's Wait time)
runSimulation("Donor Alpha", "A");

// Scenario 2: A Type O Donor (Universal Donor - Tests Timmy's Pediatric Bonus)
runSimulation("Donor Omega", "O");
```

### frontend/nativewind-env.d.ts

```typescript
/// <reference types="nativewind/types" />

```

[54 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]