refactor this code. THis is for an expo mobile app. Make sure its dynamic. 
// App.js

import React, { useState, useEffect, useRef } from 'react';
import {
  StyleSheet,
  Text,
  View,
  ScrollView,
  Button,
  Image,
  Alert,
  Platform,
} from 'react-native';
import { Camera } from 'expo-camera';
import { Audio, Video } from 'expo-av'; // Correct import
import * as Print from 'expo-print';
import * as Sharing from 'expo-sharing';

const App = () => {
  // --- Permissions States ---
  const [hasCameraPermission, setHasCameraPermission] = useState(null);
  const [hasAudioPermission, setHasAudioPermission] = useState(null);

  // --- Legal Text ---
  const legalText = `YOUR LEGAL TEXT GOES HERE...

  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vel turpis at quam aliquet lobortis. Integer sit amet ligula vitae justo commodo fermentum. Donec vitae massa a augue blandit porttitor. Proin id purus nec justo mollis finibus sit amet at justo. Mauris ac sem vitae nisl interdum interdum.`;

  // --- Photo Capture States ---
  const cameraRef = useRef(null);
  const [capturedPhoto, setCapturedPhoto] = useState(null);

  // --- Video Recording States ---
  const videoCameraRef = useRef(null);
  const [capturingVideo, setCapturingVideo] = useState(false);
  const [capturedVideo, setCapturedVideo] = useState(null);

  // --- Voice Recording States ---
  const [recording, setRecording] = useState(null);
  const [recordedAudioUri, setRecordedAudioUri] = useState(null);

  // --- On Component Mount: Request Permissions ---
  useEffect(() => {
    (async () => {
      const cameraStatus = await Camera.requestCameraPermissionsAsync();
      setHasCameraPermission(cameraStatus.status === 'granted');

      const audioStatus = await Audio.requestPermissionsAsync();
      setHasAudioPermission(audioStatus.status === 'granted');

      if (cameraStatus.status !== 'granted' || audioStatus.status !== 'granted') {
        Alert.alert(
          'Permissions Required',
          'Please grant camera and microphone permissions to use this app.',
          [{ text: 'OK' }]
        );
      }
    })();
  }, []);

  // --- Capture Photo Function ---
  const takePhoto = async () => {
    if (cameraRef.current) {
      try {
        const photo = await cameraRef.current.takePictureAsync();
        setCapturedPhoto(photo.uri);
      } catch (error) {
        Alert.alert('Error', 'Failed to take photo: ' + error.message);
      }
    }
  };

  // --- Start Video Recording ---
  const startVideoRecording = async () => {
    if (videoCameraRef.current) {
      try {
        setCapturingVideo(true);
        // Start recording
        const video = await videoCameraRef.current.recordAsync({
          maxDuration: 60, // Optional: Set maximum duration (in seconds)
          quality: Camera.Constants.VideoQuality["480p"],
        });
        setCapturedVideo(video.uri);
      } catch (error) {
        Alert.alert('Error', 'Failed to record video: ' + error.message);
      }
    }
  };

  // --- Stop Video Recording ---
  const stopVideoRecording = () => {
    if (videoCameraRef.current && capturingVideo) {
      videoCameraRef.current.stopRecording();
      setCapturingVideo(false);
    }
  };

  // --- Start Voice Recording ---
  const startVoiceRecording = async () => {
    try {
      await Audio.setAudioModeAsync({
        allowsRecordingIOS: true,
        playsInSilentModeIOS: true,
      });

      const { recording } = await Audio.Recording.createAsync(
        Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
      );
      setRecording(recording);
      Alert.alert('Recording Started', 'Speak into your microphone.');
    } catch (error) {
      Alert.alert('Error', 'Failed to start recording: ' + error.message);
    }
  };

  // --- Stop Voice Recording ---
  const stopVoiceRecording = async () => {
    try {
      await recording.stopAndUnloadAsync();
      const uri = recording.getURI();
      setRecordedAudioUri(uri);
      setRecording(null);
      Alert.alert('Recording Stopped', 'Your voice has been recorded.');
    } catch (error) {
      Alert.alert('Error', 'Failed to stop recording: ' + error.message);
    }
  };

  // --- Generate and Share PDF ---
  const generatePDF = async () => {
    // Create HTML content for PDF
    let mediaHtml = '';

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

    if (capturedVideo) {
      // Note: Embedding video in PDF is not widely supported
      mediaHtml += `<h2>Recorded Video</h2>
                    <p>Video recorded at: <a href="${capturedVideo}">Download Video</a></p>`;
    }

    if (recordedAudioUri) {
      // Note: Embedding audio in PDF is not widely supported
      mediaHtml += `<h2>Recorded Voice</h2>
                    <p>Audio recorded at: <a href="${recordedAudioUri}">Download Audio</a></p>`;
    }

    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>
          <p>${legalText}</p>
          ${mediaHtml}
        </body>
      </html>
    `;

    try {
      // Generate PDF from HTML
      const { uri } = await Print.printToFileAsync({ html: htmlContent });

      // Share or download the PDF
      await Sharing.shareAsync(uri);
    } catch (error) {
      Alert.alert('Error', 'Failed to generate PDF: ' + error.message);
    }
  };

  // --- Conditional Rendering Based on Permissions ---
  if (hasCameraPermission === null || hasAudioPermission === null) {
    return <View />;
  }
  if (hasCameraPermission === false || hasAudioPermission === false) {
    return (
      <View style={styles.permissionContainer}>
        <Text style={styles.permissionText}>
          No access to camera or microphone. Please enable permissions in your device settings.
        </Text>
      </View>
    );
  }

  return (
    <ScrollView contentContainerStyle={styles.container}>
      {/* --- Legal Text Display --- */}
      <Text style={styles.header}>Legal Information</Text>
      <Text style={styles.legalText}>{legalText}</Text>

      {/* --- Photo Capture Section --- */}
      <View style={styles.section}>
        <Text style={styles.subHeader}>Capture Photo</Text>
        {!capturedPhoto ? (
          <Camera style={styles.camera} ref={cameraRef}>
            <View style={styles.buttonContainer}>
              <Button title="Take Photo" onPress={takePhoto} />
            </View>
          </Camera>
        ) : (
          <View style={styles.mediaContainer}>
            <Image source={{ uri: capturedPhoto }} style={styles.imagePreview} />
            <Button title="Retake Photo" onPress={() => setCapturedPhoto(null)} />
          </View>
        )}
      </View>

      {/* --- Video Recording Section --- */}
      <View style={styles.section}>
        <Text style={styles.subHeader}>Record Video</Text>
        {!capturedVideo ? (
          <Camera style={styles.camera} ref={videoCameraRef}>
            <View style={styles.buttonContainer}>
              {!capturingVideo ? (
                <Button title="Start Recording" onPress={startVideoRecording} />
              ) : (
                <Button title="Stop Recording" onPress={stopVideoRecording} color="red" />
              )}
            </View>
          </Camera>
        ) : (
          <View style={styles.mediaContainer}>
            <Video
              source={{ uri: capturedVideo }}
              style={styles.videoPreview}
              useNativeControls
              resizeMode="contain"
            />
            <Button title="Record Again" onPress={() => setCapturedVideo(null)} />
          </View>
        )}
      </View>

      {/* --- Voice Recording Section --- */}
      <View style={styles.section}>
        <Text style={styles.subHeader}>Voice Recording</Text>
        {!recording ? (
          <Button title="Start Recording" onPress={startVoiceRecording} />
        ) : (
          <Button title="Stop Recording" onPress={stopVoiceRecording} color="red" />
        )}
        {recordedAudioUri && (
          <Text style={styles.recordedText}>Audio Recorded: {recordedAudioUri}</Text>
        )}
      </View>

      {/* --- PDF Generation Section --- */}
      <View style={styles.section}>
        <Button title="Download PDF" onPress={generatePDF} />
      </View>
    </ScrollView>
  );
};

// --- Styles ---
const styles = StyleSheet.create({
  container: {
    padding: 20,
    paddingBottom: 40,
    backgroundColor: '#f5f5f5',
  },
  permissionContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  permissionText: {
    fontSize: 16,
    textAlign: 'center',
    marginHorizontal: 20,
  },
  header: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  legalText: {
    fontSize: 16,
    marginBottom: 20,
    lineHeight: 22,
  },
  section: {
    marginBottom: 30,
    backgroundColor: '#ffffff',
    padding: 15,
    borderRadius: 10,
    elevation: 2, // For Android
    shadowColor: '#000', // For iOS
    shadowOffset: { width: 0, height: 2 }, // For iOS
    shadowOpacity: 0.25, // For iOS
    shadowRadius: 3.84, // For iOS
  },
  subHeader: {
    fontSize: 20,
    marginBottom: 10,
    fontWeight: '600',
  },
  camera: {
    width: '100%',
    height: 250,
    borderRadius: 10,
    overflow: 'hidden',
  },
  buttonContainer: {
    backgroundColor: 'rgba(0,0,0,0.5)',
    padding: 10,
    alignItems: 'center',
  },
  mediaContainer: {
    alignItems: 'center',
  },
  imagePreview: {
    width: '100%',
    height: 250,
    borderRadius: 10,
    marginBottom: 10,
    resizeMode: 'cover',
  },
  videoPreview: {
    width: '100%',
    height: 250,
    borderRadius: 10,
    marginBottom: 10,
  },
  recordedText: {
    marginTop: 10,
    fontSize: 14,
    color: '#333',
  },
});

export default App;