diff --git a/mobile/app/upload.tsx b/mobile/app/upload.tsx index cda28db..296e407 100644 --- a/mobile/app/upload.tsx +++ b/mobile/app/upload.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Alert } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; -import { useUpload } from '../hooks/useUpload'; +import * as DocumentPicker from 'expo-document-picker'; +import { useUpload, UploadFile } from '../hooks/useUpload'; import { UploadProgress } from '../components/UploadProgress'; export function UploadScreen() { @@ -11,6 +12,27 @@ export function UploadScreen() { const [totalCount, setTotalCount] = useState(0); const upload = useUpload(); + const doUpload = async (files: UploadFile[]) => { + setUploadStatus('uploading'); + setUploadedCount(0); + setTotalCount(files.length); + + try { + const response = await upload.mutateAsync(files); + setUploadedCount(response.uploaded.length); + + if (response.errors.length > 0) { + setUploadStatus('error'); + setError(`${response.uploaded.length}/${totalCount} uploadés. Erreurs : ${response.errors.map((e) => e.name).join(', ')}`); + } else { + setUploadStatus('success'); + } + } catch (err) { + setUploadStatus('error'); + setError(err instanceof Error ? err.message : 'Upload failed'); + } + }; + const pickImages = async () => { try { const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); @@ -25,40 +47,41 @@ export function UploadScreen() { allowsMultipleSelection: true, }); - if (result.canceled) return; + if (result.canceled || result.assets.length === 0) return; - const assets = result.assets; - if (assets.length === 0) return; - - setUploadStatus('uploading'); - setUploadedCount(0); - setTotalCount(assets.length); - - const files = assets.map((asset) => ({ + const files = result.assets.map((asset) => ({ uri: asset.uri, type: asset.mimeType || 'image/jpeg', name: asset.fileName || 'photo.jpg', })); - try { - const response = await upload.mutateAsync(files); - setUploadedCount(response.uploaded.length); - - if (response.errors.length > 0) { - setUploadStatus('error'); - setError(`${response.uploaded.length}/${totalCount} uploadés. Erreurs : ${response.errors.map((e) => e.name).join(', ')}`); - } else { - setUploadStatus('success'); - } - } catch (err) { - setUploadStatus('error'); - setError(err instanceof Error ? err.message : 'Upload failed'); - } + await doUpload(files); } catch (err) { Alert.alert('Erreur', "Impossible d'accéder à la galerie"); } }; + const pickDocuments = async () => { + try { + const result = await DocumentPicker.getDocumentAsync({ + multiple: true, + copyToCacheDirectory: true, + }); + + if (result.canceled || result.assets.length === 0) return; + + const files = result.assets.map((asset) => ({ + uri: asset.uri, + type: asset.mimeType || 'application/octet-stream', + name: asset.name, + })); + + await doUpload(files); + } catch (err) { + Alert.alert('Erreur', "Impossible de sélectionner des documents"); + } + }; + return ( Sélectionner des photos + + + Sélectionner des documents + ); } @@ -86,6 +113,13 @@ const styles = StyleSheet.create({ padding: 16, borderRadius: 8, alignItems: 'center', + marginBottom: 12, + }, + docButton: { + backgroundColor: '#4CAF50', + padding: 16, + borderRadius: 8, + alignItems: 'center', }, uploadText: { color: '#fff', diff --git a/mobile/package-lock.json b/mobile/package-lock.json index 3b0a2b3..2474a68 100644 --- a/mobile/package-lock.json +++ b/mobile/package-lock.json @@ -12,6 +12,7 @@ "@react-navigation/native-stack": "^7.17.10", "@tanstack/react-query": "^5.101.2", "expo": "~57.0.4", + "expo-document-picker": "~57.0.0", "expo-file-system": "~57.0.0", "expo-image-picker": "~57.0.2", "expo-status-bar": "~57.0.0", @@ -2798,6 +2799,15 @@ } } }, + "node_modules/expo-document-picker": { + "version": "57.0.0", + "resolved": "https://registry.npmjs.org/expo-document-picker/-/expo-document-picker-57.0.0.tgz", + "integrity": "sha512-foT1pA3tD7KvcqXwjQBh4qEDjHT9U9MhZ6H2aF38VolCiHRhXDQLtKQqCeXjbHxJhSf8HC/YPV3IRxDxFTL2sA==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-file-system": { "version": "57.0.0", "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-57.0.0.tgz", diff --git a/mobile/package.json b/mobile/package.json index 2479087..f5da8ca 100644 --- a/mobile/package.json +++ b/mobile/package.json @@ -7,6 +7,7 @@ "@react-navigation/native-stack": "^7.17.10", "@tanstack/react-query": "^5.101.2", "expo": "~57.0.4", + "expo-document-picker": "~57.0.0", "expo-file-system": "~57.0.0", "expo-image-picker": "~57.0.2", "expo-status-bar": "~57.0.0",