import React, { useState } from 'react'; import { View, StyleSheet, Alert } from 'react-native'; import { Button, Text, ProgressBar } from 'react-native-paper'; import { launchCamera } from 'react-native-image-picker'; import DocumentPicker from 'react-native-document-picker'; import axios from 'axios'; interface Props { onFileSelected: (fileName: string, s3Key: string) => void; getUploadUrl: ( fileName: string, ) => Promise<{ uploadUrl: string; s3Key: string }>; } export function FilePickerButton({ onFileSelected, getUploadUrl }: Props) { const [uploading, setUploading] = useState(false); const [progress, setProgress] = useState(0); const [fileName, setFileName] = useState(null); const uploadFile = async (uri: string, name: string, type: string) => { setUploading(true); setProgress(0); setFileName(name); try { const { uploadUrl, s3Key } = await getUploadUrl(name); const file = await fetch(uri); const blob = await file.blob(); await axios.put(uploadUrl, blob, { headers: { 'Content-Type': type }, onUploadProgress: (e) => { if (e.total) setProgress(e.loaded / e.total); }, }); onFileSelected(name, s3Key); } catch { Alert.alert( 'Upload Failed', 'Could not upload the file. Please try again.', ); setFileName(null); } finally { setUploading(false); } }; const pickDocument = async () => { try { const result = await DocumentPicker.pickSingle({ type: [DocumentPicker.types.pdf], }); if (result.uri && result.name) { await uploadFile( result.uri, result.name, result.type || 'application/pdf', ); } } catch (err) { if (!DocumentPicker.isCancel(err)) { Alert.alert('Error', 'Could not pick document.'); } } }; const takePhoto = async () => { const result = await launchCamera({ mediaType: 'photo', quality: 0.8 }); if (result.assets?.[0]?.uri) { const asset = result.assets[0]; await uploadFile( asset.uri!, asset.fileName || 'vendor-proposal.jpg', asset.type || 'image/jpeg', ); } }; return ( {uploading && } {fileName && !uploading && ( {fileName} )} ); } const styles = StyleSheet.create({ container: { gap: 8, }, buttons: { flexDirection: 'row', gap: 12, }, button: { flex: 1, }, progress: { marginTop: 4, }, fileName: { color: '#2E7D32', }, });