I keep getting undefined when I download the pdf. I want the legal text from the scrollable window to pass into the pdf generator with checkboxes and updated signature fields.
// components/LegalText.js

import React, { useState } from 'react';
import {
  ScrollView,
  Text,
  StyleSheet,
  View,
  TextInput,
} from 'react-native';
import Checkbox from 'expo-checkbox';

const LegalText = () => {
  // State for checkboxes
  const [checkboxes, setCheckboxes] = useState({
    item1: false,
    item2: false,
    item3: false,
  });

  // State for signatures
  const [person1Signature, setPerson1Signature] = useState('');
  const [person2Signature, setPerson2Signature] = useState('');

  // Get current date and time
  const now = new Date();
  const formattedDate = now.toLocaleDateString(undefined, {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });
  const formattedTime = now.toLocaleTimeString(undefined, {
    hour: '2-digit',
    minute: '2-digit',
  });

  // Handler to toggle checkboxes
  const toggleCheckbox = (item) => {
    setCheckboxes((prev) => ({
      ...prev,
      [item]: !prev[item],
    }));
  };

  return (
    <ScrollView style={styles.container}>
      {/* Title */}
      <Text style={styles.title}>Title</Text>

      {/* Checkboxes */}
      <View style={styles.checkboxContainer}>
        <Checkbox
          value={checkboxes.item1}
          onValueChange={() => toggleCheckbox('item1')}
          color={checkboxes.item1 ? '#4630EB' : undefined}
        />
        <Text style={styles.label}>Item 1</Text>
      </View>
      <View style={styles.checkboxContainer}>
        <Checkbox
          value={checkboxes.item2}
          onValueChange={() => toggleCheckbox('item2')}
          color={checkboxes.item2 ? '#4630EB' : undefined}
        />
        <Text style={styles.label}>Item 2</Text>
      </View>
      <View style={styles.checkboxContainer}>
        <Checkbox
          value={checkboxes.item3}
          onValueChange={() => toggleCheckbox('item3')}
          color={checkboxes.item3 ? '#4630EB' : undefined}
        />
        <Text style={styles.label}>Item 3</Text>
      </View>

      {/* Signatures */}
      <View style={styles.signatureContainer}>
        <Text style={styles.signatureLabel}>Person 1 Signature:</Text>
        <TextInput
          style={styles.input}
          placeholder="Enter signature"
          value={person1Signature}
          onChangeText={setPerson1Signature}
        />
      </View>

      <View style={styles.signatureContainer}>
        <Text style={styles.signatureLabel}>Person 2 Signature:</Text>
        <TextInput
          style={styles.input}
          placeholder="Enter signature"
          value={person2Signature}
          onChangeText={setPerson2Signature}
        />
      </View>

      {/* Date and Time */}
      <Text style={styles.datetime}>
        Date: {formattedDate} {'\n'} Time: {formattedTime}
      </Text>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    textAlign: 'center',
    marginVertical: 20,
  },
  checkboxContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 10,
  },
  label: {
    marginLeft: 8,
    fontSize: 16,
  },
  signatureContainer: {
    marginTop: 20,
  },
  signatureLabel: {
    fontSize: 16,
    marginBottom: 5,
  },
  input: {
    borderBottomWidth: 1,
    borderColor: '#000',
    paddingVertical: 5,
    fontSize: 16,
  },
  datetime: {
    marginTop: 30,
    fontSize: 16,
    textAlign: 'right',
    lineHeight: 22, // Adjust line height for better readability
  },
});

export default LegalText;

// App.js (Updated to 75% Screen Height)

import React from 'react';
import { StyleSheet, Text, View, ScrollView, Dimensions } from 'react-native';
import usePermissions from './hooks/usePermissions';
import PhotoCapture from './components/PhotoCapture';
import VideoRecording from './components/VideoRecording';
import VoiceRecording from './components/VoiceRecording';
import PDFGenerator from './components/PDFGenerator';
import LegalText from './components/LegalText'; // Import LegalText component
import { MediaProvider } from './context/MediaContext';

const screenHeight = Dimensions.get('window').height;

const App = () => {
  const { hasCameraPermission, hasAudioPermission, hasStoragePermission } = usePermissions();

  // Show loading screen while permissions are being determined
  if (
    hasCameraPermission === null ||
    hasAudioPermission === null ||
    hasStoragePermission === null
  ) {
    return <View style={styles.loadingContainer} />;
  }

  // Show permission denial message if any permission is not granted
  if (
    !hasCameraPermission ||
    !hasAudioPermission ||
    !hasStoragePermission
  ) {
    return (
      <View style={styles.permissionContainer}>
        <Text style={styles.permissionText}>
          No access to camera, microphone, or storage. Please enable permissions in your device settings.
        </Text>
      </View>
    );
  }

  // Main App Content
  return (
    <MediaProvider>
      <ScrollView contentContainerStyle={styles.container}>
        {/* --- Header --- */}
        <Text style={styles.header}>Consent Form</Text>

        {/* --- Legal Text Display --- */}
        <View style={styles.legalTextContainer}>
          <ScrollView
            nestedScrollEnabled={true} // Enables independent scrolling within this ScrollView
            contentContainerStyle={styles.legalTextInnerContainer}
            showsVerticalScrollIndicator={true} // Optional: Show scroll indicators
          >
            <LegalText />
          </ScrollView>
        </View>

        {/* --- Photo Capture Section --- */}
        <PhotoCapture />

        {/* --- Video Recording Section --- */}
        {/* <VideoRecording /> */}

        {/* --- Voice Recording Section --- */}
        <VoiceRecording />

        {/* --- PDF Generation Section --- */}
        <PDFGenerator />
      </ScrollView>
    </MediaProvider>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
    paddingBottom: 40,
    backgroundColor: '#f5f5f5',
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  permissionContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  permissionText: {
    fontSize: 16,
    textAlign: 'center',
    color: '#ff0000',
  },
  header: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  legalTextContainer: {
    height: screenHeight * 0.75, // Changed from 0.6 (60%) to 0.75 (75%) of screen height
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 8,
    padding: 10,
    backgroundColor: '#fff',
    marginBottom: 20, // Add some margin below
  },
  legalTextInnerContainer: {
    paddingVertical: 5,
  },
});

export default App;

import React, { useContext, useState } from 'react';
import {
  StyleSheet,
  View,
  Button,
  Alert,
  TouchableOpacity,
  Text,
  ActivityIndicator,
  Platform,
} from 'react-native';
import * as Print from 'expo-print';
import * as FileSystem from 'expo-file-system';
import { StorageAccessFramework } from 'expo-file-system';
import * as Sharing from 'expo-sharing';
import { MediaContext } from '../context/MediaContext';
import { Ionicons } from '@expo/vector-icons';

const PDFGenerator = () => {
  const { media } = useContext(MediaContext);
  const [pdfUri, setPdfUri] = useState(null);
  const [isGenerating, setIsGenerating] = useState(false);

  const generatePDF = async () => {
    setIsGenerating(true);

    // Create HTML content for PDF
    let mediaHtml = '';

    if (media.photo) {
      mediaHtml += `<h2>Captured Photo</h2><img src="${media.photo}" style="width:100%; height:auto;" />`;
    }

    if (media.video) {
      mediaHtml += `<h2>Recorded Video</h2>
                    <p>Video recorded at: <a href="${media.video}">Download Video</a></p>`;
    }

    if (media.audio) {
      mediaHtml += `<h2>Recorded Voice</h2>
                    <p>Audio recorded at: <a href="${media.audio}">Download Audio</a></p>`;
    }

    // Get current date and time for filename
    const now = new Date();
    const formattedDate = now.toLocaleDateString(undefined, {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit'
    }).replace(/\//g, '-');
    
    const formattedTime = now.toLocaleTimeString(undefined, {
      hour: '2-digit',
      minute: '2-digit'
    }).replace(/:/g, '-').replace(/\s/g, '');

    const filename = `ConsentDocument_${formattedDate}_${formattedTime}.pdf`;

    const htmlContent = `
      <html>
        <head>
          <style>
            body { font-family: Arial, sans-serif; padding: 20px; }
            h1 { text-align: center; }
            img { max-width: 100%; height: auto; }
            a { color: blue; text-decoration: none; }
          </style>
        </head>
        <body>
          <h1>Consent Document</h1>
          ${mediaHtml}
          <div>
            <h2>Signatures:</h2>
            <p>Person 1: ____________________</p>
            <p>Person 2: ____________________</p>
            <p>Date: ${now.toLocaleDateString()}</p>
            <p>Time: ${now.toLocaleTimeString()}</p>
          </div>
        </body>
      </html>
    `;

    try {
      const { uri } = await Print.printToFileAsync({ html: htmlContent });
      
      if (Platform.OS === 'android') {
        const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();

        if (!permissions.granted) {
          Alert.alert('Permission Required', 'Storage permission is needed to save the PDF.');
          setIsGenerating(false);
          return;
        }

        try {
          const fileUri = await StorageAccessFramework.createFileAsync(
            permissions.directoryUri,
            filename,
            'application/pdf'
          );

          const pdfData = await FileSystem.readAsStringAsync(uri, {
            encoding: FileSystem.EncodingType.Base64,
          });

          await FileSystem.writeAsStringAsync(fileUri, pdfData, {
            encoding: FileSystem.EncodingType.Base64,
          });

          setPdfUri(fileUri);
          Alert.alert('Success', `PDF has been saved as ${filename}`);
        } catch (e) {
          console.error('Error saving PDF:', e);
          Alert.alert('Error', 'Failed to save PDF: ' + e.message);
        }
      } else {
        const destinationPath = `${FileSystem.documentDirectory}${filename}`;

        await FileSystem.moveAsync({
          from: uri,
          to: destinationPath,
        });

        setPdfUri(destinationPath);

        if (await Sharing.isAvailableAsync()) {
          await Sharing.shareAsync(destinationPath);
        } else {
          Alert.alert('Success', `PDF has been saved as ${filename} in your Documents directory.`);
        }
      }
    } catch (error) {
      Alert.alert('Error', 'Failed to generate PDF: ' + error.message);
      console.error('Error generating PDF:', error);
    }

    setIsGenerating(false);
  };

  const openDownloadLocation = async () => {
    if (!pdfUri) {
      Alert.alert('No PDF', 'Please generate the PDF first.');
      return;
    }

    try {
      if (Platform.OS === 'android') {
        Alert.alert(
          'Download Complete',
          'The PDF has been saved successfully. You can access it using any file manager app.'
        );
      } else if (Platform.OS === 'ios') {
        if (await Sharing.isAvailableAsync()) {
          await Sharing.shareAsync(pdfUri);
        } else {
          Alert.alert('Sharing Not Available', 'Cannot share the PDF on this device.');
        }
      } else {
        Alert.alert('Unsupported Platform', 'This feature is not supported on your device.');
      }
    } catch (error) {
      Alert.alert('Error', 'Cannot open the PDF. Please try again.');
      console.error('Error opening PDF:', error);
    }
  };

  return (
    <View style={styles.container}>
      <View style={styles.section}>
        <Button title="Download PDF" onPress={generatePDF} disabled={isGenerating} />
      </View>
      {isGenerating && <ActivityIndicator size="large" color="#0000ff" />}
      {pdfUri && (
        <TouchableOpacity style={styles.iconContainer} onPress={openDownloadLocation}>
          <Ionicons name="folder-open" size={40} color="#4CAF50" />
          <Text style={styles.iconText}>Open Download Location</Text>
        </TouchableOpacity>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  section: {
    marginBottom: 30,
    backgroundColor: '#ffffff',
    padding: 15,
    borderRadius: 10,
    elevation: 2,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    alignItems: 'center',
  },
  iconContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginTop: 10,
    padding: 10,
    backgroundColor: '#e0f7fa',
    borderRadius: 10,
  },
  iconText: {
    marginLeft: 10,
    fontSize: 16,
    color: '#00796b',
  },
});

export default PDFGenerator;