# Project export: PathSafe

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: UC Berkeley AI Hackathon 2025
- Tagline: PathSafe is an AI-powered safety and advocacy hub that helps users navigate the safest walking routes, stay alert to nearby threats, and connect through community-verified protests and events.
- Devpost: https://devpost.com/software/path-safe
- GitHub: https://github.com/XenobyteDev/PathSafe
- Demo: https://github.com/Apapaya/AAAS
- Team: 3 GitHub contributor(s) — XenobyteDev (12 commits), Angelo Payavala (5 commits), cummin-alexander-r01 (5 commits)

## Devpost submission (written by the team)

### Overview

PathSafe is an AI-powered safety and advocacy hub that helps users navigate the safest walking routes, stay alert to nearby threats, and connect through community-verified protests and events.

### Inspiration

We were inspired by the rising need for grassroots safety infrastructure — especially for individuals from marginalized or at-risk communities. While navigating cities, many people don’t have access to real-time threat data or safe routing options, particularly when moving on foot. We wanted to create a tool that empowers users not only to stay informed and protected, but also to engage in advocacy and mutual aid efforts by participating in verified protests and community events. What It Does PathSafe helps users: Detect nearby dangerous activity based on community reports. View risk zones visualized on a live map. Receive AI-generated safe walking routes that avoid threats. Submit and view reports from others in the area. Check safety levels at specific locations. View upcoming protests and confirm attendance. Access local support resources like shelters or aid hubs. How We Built It Frontend: Built using React Native (Expo), with Mapbox for map visualization and geolocation, plus Lucide icons for clean UI. Backend: Node.js with Express, featuring RESTful APIs for report submission, safety checks, and route generation. Database: MongoDB to store incident reports and event data. AI Integration: Python backend used to calculate optimal routes avoiding reported danger zones using geo-fencing and custom heuristics. Map Routing: Combined Mapbox GL and Directions API for pathfinding, augmented with custom threat logic. Deployment: Backend runs locally for demo, but can be containerized with Docker; frontend is deployable via Expo. What We Learned How to integrate AI-assisted routing logic with geospatial data. The complexity of translating real-world safety concerns into functional, accessible UX. Handling geolocation, heatmaps, and point annotations in Mapbox within a React Native mobile environment. Designing for real-time updates and reliability in safety-critical contexts. Challenges We Ran Into Getting accurate geospatial calculations while filtering real-time threat zones. Managing state across components when syncing user location, map interactions, and backend data. Making the map UI responsive and intuitive across devices. Accomplishments We’re Proud Of Seamless integration of live maps, AI-based routing, and real-time community input. Built a mobile safety tool with real-world applications under tight time constraints. Developed a prototype that is both technically functional and socially impactful. What's Next for PathSafe Add SMS or push notifications for alerts in high-risk areas. Improve AI route prediction with more robust historical data. Gamify safety reporting to encourage wider participation. Enable users to mark “safe zones” like community centers, pop-up shelters, or check-in spots. Add multilingual support and accessibility features. Deploy a scalable version for real-world pilots with community partners. Disclaimer: This app is for educational and demonstration purposes only. It is not intended to replace official safety guidance or emergency services.

## README (from the GitHub repository)

# PathSafe

PathSafe is a safety navigation tool that helps individuals avoid known ICE activity areas based on real-time, community-submitted reports. Designed for humanitarian aid and immigrant safety, this app routes users away from risk zones and toward support resources.

## 🏗️ Project Structure
PathSafe/

├── backend/            # Express backend (API endpoints)

├── frontend/           # React Native (or other framework) frontend

├── .gitignore          # Git ignore file

├── package.json        # Project metadata & dependencies

├── README.md           # Project overview and setup

└── LICENSE             # License for the project

## 📦 Backend Setup

1. Navigate to the backend folder:
   ```bash
   cd backend
   ```

2. Install dependencies:
   ```bash
   npm install
   ```

3. Start the backend server:
   ```bash
   npm start
   ```
   
4. Server runs at: [http://localhost:3000/](http://localhost:3000/)

### API Endpoints
* ```POST /report```: Submit ICE sighting reports
* ```GET /safety?lat=...&lng=...```: Check risk level near given coordinates
* ```GET /resources```: Get a list of safe locations/resources

## 🎨 Frontend Overview
Frontend allows users to:

* Submit sightings via a map interface
* View heatmaps of recent reports
* Get directions away from risky areas
* Find nearby legal/shelter resources

**Tech Stack:**
* **Frontend**: React Native (Expo), Mapbox/Leaflet, Axios for API requests
* **Backend**: Express.js (Node.js), MongoDB for database (or any other DB as needed)
* **Deployment**: Docker (for backend deployment), Expo (for mobile app deployment)

---

## 🚀 Team

* Angelo Payavala – UI/Frontend Lead
* Alexander Cummin – Frontend and Backend Developer
* Arfana Sham – AI/Data
* Sagar Kapri – Data & Research

---

## 💡 Inspiration
Created at the 2025 UC Berkeley AI Hackathon in response to humanitarian safety challenges. This project aims to provide a real-time, community-driven safety tool using AI-assisted decision-making and mapping.

---

⚠️ Disclaimer: This project is for educational and demonstration purposes only. It does not provide guaranteed safety, legal advice, or official immigration guidance.

## Detected evidence (automated analysis)

Indexed codebase: 25 recognized source files, 84 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- TypeScript (language) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (36 of 36)

```
.expo/devices.json
.expo/README.md
.gitignore
backend/index.js
backend/package.json
backend/README.md
frontend/.gitignore
frontend/package.json
frontend/public/index.html
frontend/public/manifest.json
frontend/public/robots.txt
frontend/README.md
frontend/src/App.css
frontend/src/App.js
frontend/src/App.test.js
frontend/src/index.css
frontend/src/index.js
frontend/src/MapReport.jsx
frontend/src/ReportForm.jsx
frontend/src/reportWebVitals.js
frontend/src/setupTests.js
package.json
README.md
UI/app.json
UI/app/_layout.tsx
UI/app/(tabs)/_layout.tsx
UI/app/(tabs)/community.tsx
UI/app/(tabs)/index.tsx
UI/app/(tabs)/rights.tsx
UI/app/+not-found.tsx
UI/components/BottomSheet.tsx
UI/components/MapPlaceholder.tsx
UI/expo-env.d.ts
UI/hooks/useFrameworkReady.ts
UI/package.json
UI/tsconfig.json
```

### Dependencies

- backend/package.json: body-parser@^1.20.2, cors@^2.8.5, express@^4.18.2
- frontend/package.json: @testing-library/dom@^10.4.0, @testing-library/jest-dom@^6.6.3, @testing-library/react@^16.3.0, @testing-library/user-event@^13.5.0, mapbox-gl@^3.13.0, react@^19.1.0, react-dom@^19.1.0, react-map-gl@^8.0.4, react-scripts@^5.0.1, web-vitals@^2.1.4
- package.json: @expo/metro-runtime@~5.0.4, @types/react@~19.0.10, concurrently@^8.0.0, expo@^53.0.12, mapbox-gl@^3.13.0, maplibre-gl@^5.6.0, react@^19.1.0, react-dom@^19.1.0, react-map-gl@^6.1.21, react-native-web@^0.20.0, typescript@~5.8.3
- UI/package.json: @babel/core@^7.25.2, @expo-google-fonts/inter@^0.2.3, @expo/cli@^0.22.3, @expo/vector-icons@^14.1.0, @lucide/lab@^0.1.2, @react-navigation/bottom-tabs@^7.2.0, @react-navigation/native@^7.0.14, @types/react@~19.0.10, expo@^53.0.12, expo-blur@~14.1.3, expo-camera@~16.1.5, expo-constants@~17.1.3, expo-font@~13.2.2, expo-haptics@~14.1.3, expo-linear-gradient@~14.1.3, expo-linking@~7.1.3, expo-location@~18.1.2, expo-router@~5.0.2, expo-splash-screen@~0.30.6, expo-status-bar@~2.2.2, expo-symbols@~0.4.3, expo-system-ui@~5.0.5, expo-web-browser@~14.1.5, lucide-react-native@^0.475.0, react@19.0.0, react-dom@19.0.0, react-native@0.79.1, react-native-gesture-handler@~2.24.0, react-native-reanimated@~3.17.4, react-native-safe-area-context@5.3.0, react-native-screens@~4.10.0, react-native-svg@15.11.2, react-native-url-polyfill@^2.0.0, react-native-web@^0.20.0, react-native-webview@13.13.5, typescript@~5.8.3

### Recent commits (newest first)

- Update README
- Resolved merge conflicts in .gitignore and package.json
- Get access to AAAS folder in original repo
- Add previous version of PathSafe before UI integration
- Updated UI with new components and changes
- Remove heat map and restore map functionality
- Merge branch 'main' of https://github.com/Apapaya/AAAS
- Removed trustScore for demo
- Clean up MapReport.jsx
- Merge branch 'main' of https://github.com/Apapaya/AAAS
- Add interactive MapBox map for location-based reporting
- UI Push
- Initial commit of AAAS Expo app
- Merge remote and local histories
- Merge branch 'main' of https://github.com/Apapaya/AAAS
- Add ReportForm componenet and update App.js to use it
- Add backend server setup and API endpoints
- Add backend server setup and API endpoints
- Add .gitignore
- Add .gitignore

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

### package.json

```
{
  "name": "pathsafe",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "concurrently \"npm run start --prefix frontend\" \"npm run start --prefix backend\"",
    "install": "npm install --prefix frontend && npm install --prefix backend",
    "build": "concurrently \"npm run build --prefix frontend\" \"npm run build --prefix backend\"",
    "test": "concurrently \"npm run test --prefix frontend\" \"npm run test --prefix backend\""
  },
  "dependencies": {
    "expo": "^53.0.12",
    "mapbox-gl": "^3.13.0",
    "maplibre-gl": "^5.6.0",
    "react": "^19.1.0",
    "react-dom": "^19.1.0",
    "react-map-gl": "^6.1.21",
    "react-native-web": "^0.20.0",
    "@expo/metro-runtime": "~5.0.4",
    "concurrently": "^8.0.0"
  },
  "devDependencies": {
    "typescript": "~5.8.3",
    "@types/react": "~19.0.10"
  }
}

```

### backend/package.json

```
{
  "name": "pathsafe-backend",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "body-parser": "^1.20.2"
  }
}

```

### frontend/package.json

```
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/dom": "^10.4.0",
    "@testing-library/jest-dom": "^6.6.3",
    "@testing-library/react": "^16.3.0",
    "@testing-library/user-event": "^13.5.0",
    "mapbox-gl": "^3.13.0",
    "react": "^19.1.0",
    "react-dom": "^19.1.0",
    "react-map-gl": "^8.0.4",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "set PORT=3001 && react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "description": "This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).",
  "main": "index.js",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "react-scripts": "^5.0.1"
  }
}

```

### UI/package.json

```
{
  "name": "dream-activist-app",
  "main": "expo-router/entry",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "EXPO_NO_TELEMETRY=1 npx expo start",
    "dev": "EXPO_NO_TELEMETRY=1 npx expo start",
    "build:web": "expo export --platform web",
    "lint": "expo lint"
  },
  "dependencies": {
    "@expo-google-fonts/inter": "^0.2.3",
    "@expo/vector-icons": "^14.1.0",
    "@lucide/lab": "^0.1.2",
    "@react-navigation/bottom-tabs": "^7.2.0",
    "@react-navigation/native": "^7.0.14",
    "expo": "^53.0.12",
    "expo-blur": "~14.1.3",
    "expo-camera": "~16.1.5",
    "expo-constants": "~17.1.3",
    "expo-font": "~13.2.2",
    "expo-haptics": "~14.1.3",
    "expo-linear-gradient": "~14.1.3",
    "expo-linking": "~7.1.3",
    "expo-location": "~18.1.2",
    "expo-router": "~5.0.2",
    "expo-splash-screen": "~0.30.6",
    "expo-status-bar": "~2.2.2",
    "expo-symbols": "~0.4.3",
    "expo-system-ui": "~5.0.5",
    "expo-web-browser": "~14.1.5",
    "lucide-react-native": "^0.475.0",
    "react": "19.0.0",
    "react-dom": "19.0.0",
    "react-native": "0.79.1",
    "react-native-gesture-handler": "~2.24.0",
    "react-native-reanimated": "~3.17.4",
    "react-native-safe-area-context": "5.3.0",
    "react-native-screens": "~4.10.0",
    "react-native-svg": "15.11.2",
    "react-native-url-polyfill": "^2.0.0",
    "react-native-web": "^0.20.0",
    "react-native-webview": "13.13.5"
  },
  "devDependencies": {
    "@babel/core": "^7.25.2",
    "@expo/cli": "^0.22.3",
    "@types/react": "~19.0.10",
    "typescript": "~5.8.3"
  }
}

```

### backend/index.js

```javascript
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();
const PORT = process.env.PORT || 3000;

app.use(cors());
app.use(bodyParser.json());

// In-memory data stores
const reports = [];
const resources = [
  { name: "Community Legal Aid", lat: 37.8715, lng: -122.2730 },
  { name: "Safe Church", lat: 37.8700, lng: -122.2690 }
];

// Health check endpoint
app.get('/', (req, res) => res.send('PathSafe Backend Running'));

// Endpoint to submit ICE sightings
app.post('/report', (req, res) => {
  const { lat, lng, type, trustScore, timestamp } = req.body;

  if (typeof lat !== 'number' || typeof lng !== 'number' || !type) {
    return res.status(400).json({ error: 'lat, lng (numbers) and type are required' });
  }

  const report = {
    lat, lng,
    type,
    trustScore: 1, // Ignore trustScore (set to 1) for demo
    timestamp: timestamp || new Date().toISOString()
  };

  reports.push(report);

  console.log("Current reports: ", reports);

  res.json({ message: 'Report received', report });
});

// Show current ICE reports
app.get('/reports', (req, res) => res.json(reports));

// Helper function: Approximate distance check (bounding box)
function isNearby(lat1, lng1, lat2, lng2, radiusInDegrees) {
  return Math.abs(lat1 - lat2) < radiusInDegrees && Math.abs(lng1 - lng2) < radiusInDegrees;
}

// Endpoint to check risk level near given coordinates
app.get('/safety', (req, res) => {
  const lat = parseFloat(req.query.lat);
  const lng = parseFloat(req.query.lng);
  
  if (isNaN(lat) || isNaN(lng)) {
    return res.status(400).json({ error: 'lat and lng (numbers) required' });
  }

  const radius = 0.01;
  const riskReports = reports.filter(r =>
    r.type === 'ICE' && isNearby(r.lat, r.lng, lat, lng, radius)
  );

  const score = riskReports.length;
  const riskLevel = score > 3 ? 'HIGH' : score > 0 ? 'MEDIUM' : 'LOW';

  res.json({ riskScore: score, riskLevel, nearbyReports: riskReports });
});

// Endpoint to list resources
app.get('/resources', (req, res) => res.json(resources));

// Start the server
app.listen(PORT, () => console.log(`PathSafe backend listening on port ${PORT}`));
```

### frontend/src/index.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

```

### UI/app/_layout.tsx

```typescript
import { useEffect } from 'react';
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import { useFrameworkReady } from '@/hooks/useFrameworkReady';
import { useFonts } from 'expo-font';
import {
  Inter_400Regular,
  Inter_500Medium,
  Inter_600SemiBold,
  Inter_700Bold
} from '@expo-google-fonts/inter';
import * as SplashScreen from 'expo-splash-screen';

SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
  useFrameworkReady();

  const [fontsLoaded, fontError] = useFonts({
    'Inter-Regular': Inter_400Regular,
    'Inter-Medium': Inter_500Medium,
    'Inter-SemiBold': Inter_600SemiBold,
    'Inter-Bold': Inter_700Bold,
  });

  useEffect(() => {
    if (fontsLoaded || fontError) {
      SplashScreen.hideAsync();
    }
  }, [fontsLoaded, fontError]);

  if (!fontsLoaded && !fontError) {
    return null;
  }

  return (
    <>
      <Stack screenOptions={{ headerShown: false }}>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
        <Stack.Screen name="+not-found" />
      </Stack>
      <StatusBar style="auto" />
    </>
  );
}
```

### frontend/src/App.js

```javascript
import React, { useState } from "react";
import MapReport from "./MapReport";

function App() {
  const [clickedCoords, setClickedCoords] = useState(null);
  const [type, setType] = useState("ICE");
  const [message, setMessage] = useState("");

  const submitReport = async (e) => {
    e.preventDefault();
    if (!clickedCoords) return;

    const report = {
      lat: clickedCoords.lat,
      lng: clickedCoords.lng,
      type,
      // No trustScore for demo
      timestamp: new Date().toISOString(),
    };

    try {
      const res = await fetch("http://localhost:3000/report", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(report),
      });

      const data = await res.json();
      setMessage(data.message || "Report submitted!");
    } catch (err) {
      console.error(err);
      setMessage("Error submitting report.");
    }
  };

  return (
    <div style={{ padding: 20 }}>
      <h2>Click on the Map to Set a Report Location</h2>
      <MapReport onMapClick={setClickedCoords} />

      {clickedCoords && (
        <form onSubmit={submitReport} style={{ marginTop: 20 }}>
          <p>
            Selected Location:{" "}
            <strong>
              {clickedCoords.lat.toFixed(4)}, {clickedCoords.lng.toFixed(4)}
            </strong>
          </p>
          <label>
            Type:{" "}
            <select value={type} onChange={(e) => setType(e.target.value)}>
              <option value="ICE">ICE</option>
              <option value="Other">Other</option>
            </select>
          </label>
          <br />
          {/* Removed trustScore input for demo */}
          <button type="submit" style={{ marginTop: 10 }}>
            Submit Report
          </button>
        </form>
      )}

      {message && <p>{message}</p>}
    </div>
  );
}

export default App;
```

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

```typescript
import { Tabs } from 'expo-router';
import { StyleSheet, Platform } from 'react-native';
import { Map, Users, Shield } from 'lucide-react-native';

export default function TabLayout() {
  return (
    <Tabs
      screenOptions={{
        headerShown: false,
        tabBarActiveTintColor: '#1E40AF',
        tabBarInactiveTintColor: '#6B7280',
        tabBarStyle: {
          backgroundColor: '#FFFFFF',
          borderTopWidth: 1,
          borderTopColor: '#E5E7EB',
          paddingTop: 8,
          paddingBottom: Platform.OS === 'ios' ? 32 : 16,
          height: Platform.OS === 'ios' ? 88 : 72,
          shadowColor: '#000',
          shadowOffset: { width: 0, height: -2 },
          shadowOpacity: 0.1,
          shadowRadius: 8,
          elevation: 8,
        },
        tabBarLabelStyle: {
          fontFamily: 'Inter-Medium',
          fontSize: 11,
          marginTop: 4,
        },
      }}>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Map',
          tabBarIcon: ({ size, color }) => (
            <Map size={size} color={color} strokeWidth={2.5} />
          ),
        }}
      />
      <Tabs.Screen
        name="community"
        options={{
          title: 'Community',
          tabBarIcon: ({ size, color }) => (
            <Users size={size} color={color} strokeWidth={2.5} />
          ),
        }}
      />
      <Tabs.Screen
        name="rights"
        options={{
          title: 'Rights & Resources',
          tabBarIcon: ({ size, color }) => (
            <Shield size={size} color={color} strokeWidth={2.5} />
          ),
        }}
      />
    </Tabs>
  );
}
```

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

```typescript
import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  StyleSheet,
  TextInput,
  TouchableOpacity,
  Alert,
  Platform,
  StatusBar,
  Dimensions,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { Search, Mic, Navigation, User, MapPin, Chrome as Home, Briefcase, Users as UsersIcon } from 'lucide-react-native';
import MapPlaceholder from '@/components/MapPlaceholder';
import BottomSheet from '@/components/BottomSheet';

const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');

interface RiskArea {
  id: string;
  location: string;
  riskLevel: 'low' | 'medium' | 'high';
  type: string;
  lastReported: string;
  coordinates: [number, number];
  radius: number;
}

interface RouteInfo {
  destination: string;
  duration: string;
  riskLevel: 'low' | 'medium' | 'high';
  alternatives: number;
}

export default function MapScreen() {
  const [searchQuery, setSearchQuery] = useState('');
  const [userLocation, setUserLocation] = useState<[number, number]>([-122.4194, 37.7749]); // Default to SF

  const nearbyRisks: RiskArea[] = [
    {
      id: '1',
      location: 'Downtown Transit Center',
      riskLevel: 'high',
      type: 'ICE checkpoint reported',
      lastReported: '15 min ago',
      coordinates: [-122.4094, 37.7849],
      radius: 50
    },
    {
      id: '2',
      location: 'Highway 101 North',
      riskLevel: 'medium',
      type: 'Heavy patrol presence',
      lastReported: '45 min ago',
      coordinates: [-122.4294, 37.7649],
      radius: 75
    },
    {
      id: '3',
      location: 'Market Street',
      riskLevel: 'low',
      type: 'All clear - community verified',
      lastReported: '2 hours ago',
      coordinates: [-122.4394, 37.7549],
      radius: 30
    }
  ];

  const recentRoutes: RouteInfo[] = [
    {
      destination: 'Community Center',
      duration: '12 min',
      riskLevel: 'low',
      alternatives: 3
    },
    {
      destination: 'Legal Aid Office',
      duration: '8 min',
      riskLevel: 'low',
      alternatives: 2
    },
    {
      destination: 'Immigration Services',
      duration: '18 min',
      riskLevel: 'medium',
      alternatives: 4
    }
  ];

  const handleSearch = () => {
    if (!searchQuery.trim()) {
      Alert.alert('Enter Destination', 'Please enter where you want to go for the safest route.');
      return;
    }
    
    // Simulate route calculation
    Alert.alert(
      'Route Calculated',
      `Finding the safest route to ${searchQuery}.\n\nRoute analysis complete:\n• Low risk detected\n• Estimated time: 15 minutes\n• 3 alternative routes available`,
      [
        { text: 'View Alternatives', style: 'default' },
        { text: 'Start Navigation', style: 'default' }
      ]
    );
  };

  const handleQuickAction = (destination: string) => {
    setSearchQuery(destination);
    handleSearch();
  };

  return (
    <GestureHandlerRootView style={styles.container}>
      <StatusBar barStyle="dark-content" backgroundColor="transparent" translucent />
      
      {/* Map */}
      <MapPlaceholder
        userLocation={userLocation}
        riskAreas={nearbyRisks}
      />

      {/* Search Bar Overlay */}
      <SafeAreaView style={styles.searchOverlay} edges={['top']}>
        <View style={styles.searchContainer}>
          <View style={styles.searchBar}>
            <Search size={20} color="#6B7280" strokeWidth={2} />
            <TextInput
              style={styles.searchInput}
              placeholder="Where do you need to go?"
              placeholderTextColor="#9CA3AF"
              value={searchQuery}
              onChangeText={setSearchQuery}
              onSubmitEditing={handleSearch}
            />
            <TouchableOpacity style={styles.micButton}>
              <Mic size={18} color="#6B7280" strokeWidth={2} />
            </TouchableOpacity>
          </View>
          <TouchableOpacity style={styles.profileButton}>
            <User size={20} color="#1E40AF" strokeWidth={2.5} />
          </TouchableOpacity>
        </View>

        {/* Quick Actions */}
        <View style={styles.quickActions}>
          <TouchableOpacity 
            style={styles.quickAction}
            onPress={() => handleQuickAction('Home')}
          >
            <Home size={16} color="#1E40AF" strokeWidth={2} />
            <Text style={styles.quickActionText}>Home</Text>
          </TouchableOpacity>
          <TouchableOpacity 
            style={styles.quickAction}
            onPress={() => handleQuickAction('Work')}
          >
            <Briefcase size={16} color="#1E40AF" strokeWidth={2} />
            <Text style={styles.quickActionText}>Work</Text>
          </TouchableOpacity>
          <TouchableOpacity 
            style={styles.quickAction}
            onPress={() => handleQuickAction('Legal Aid')}
          >
            <Navigation size={16} color="#1E40AF" strokeWidth={2} />
            <Text style={styles.quickActionText}>Legal Aid</Text>
          </TouchableOpacity>
          <TouchableOpacity 
            style={styles.quickAction}
            onPress={() => handleQuickAction('Community Center')}
          >
            <UsersIcon size={16} color="#1E40AF" strokeWidth={2} />
            <Text style={styles.quickActionText}>Community</Text>
          </TouchableOpacity>
        </View>
      </SafeAreaView>

      {/* Bottom Sheet */}
      <BottomSheet 
        nearbyRisks={nearbyRisks}
        recentRoutes={recentRoutes}
      />
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F9FAFB',
  },
  searchOverlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    zIndex: 1000,
    paddingTop: Platform.OS === 'ios' ? 40 : 32,
  },
  searchContainer: {
    flexDirection: 'row',
    paddingHorizontal: 16,
    paddingTop: 32,
    paddingBottom: 16,
 
[truncated — 1769 more characters]
```

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