move files into folders

This commit is contained in:
m
2026-07-13 17:07:00 +02:00
parent 07b03562b1
commit 04b6dfc6d4
8 changed files with 204 additions and 4 deletions
+60 -1
View File
@@ -4,7 +4,7 @@ import { useNavigation } from '@react-navigation/native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useFiles, useFileImage, useDeleteFile, useAddTags } from '../hooks/useFiles';
import { useFiles, useFileImage, useDeleteFile, useAddTags, useMoveFiles, useFolders } from '../hooks/useFiles';
import { FileItem, isFolder } from '../types';
import { SearchBar, SearchFilters } from '../components/SearchBar';
import { FileThumbnail } from '../components/FileThumbnail';
@@ -140,6 +140,9 @@ export function HomeScreen() {
const [tagModalMode, setTagModalMode] = useState<'tag' | 'folder'>('tag');
const [tagInput, setTagInput] = useState('');
const addTags = useAddTags();
const moveFiles = useMoveFiles();
const { data: foldersData } = useFolders();
const [moveModalVisible, setMoveModalVisible] = useState(false);
useEffect(() => {
const show = Keyboard.addListener('keyboardDidShow', () => setKeyboardOpen(true));
@@ -229,6 +232,13 @@ export function HomeScreen() {
setSelectedIds(new Set());
}, [tagInput, selectedIds, tagModalMode, addTags]);
const handleMove = useCallback(async (folderId: string | null) => {
const ids = Array.from(selectedIds);
await moveFiles.mutateAsync({ fileIds: ids, parentFileId: folderId });
setMoveModalVisible(false);
setSelectedIds(new Set());
}, [selectedIds, moveFiles]);
const handleItemPress = useCallback((file: FileItem) => {
if (selectionMode) {
toggleSelection(file.id);
@@ -364,6 +374,13 @@ export function HomeScreen() {
<MaterialIcons name="create-new-folder" size={20} color="#F57C00" />
<Text style={[styles.selectionActionText, { color: '#F57C00' }]}>Folder</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.selectionActionBtn, styles.moveActionBtn]}
onPress={() => setMoveModalVisible(true)}
>
<MaterialIcons name="drive-file-move" size={20} color="#00897B" />
<Text style={[styles.selectionActionText, { color: '#00897B' }]}>Déplacer</Text>
</TouchableOpacity>
</View>
</View>
) : (
@@ -422,6 +439,31 @@ export function HomeScreen() {
</TouchableOpacity>
</TouchableOpacity>
</Modal>
<Modal visible={moveModalVisible} transparent animationType="fade" onRequestClose={() => setMoveModalVisible(false)}>
<TouchableOpacity style={styles.modalOverlay} activeOpacity={1} onPress={() => setMoveModalVisible(false)}>
<TouchableOpacity activeOpacity={1} style={styles.modalContent} onPress={() => {}}>
<Text style={styles.modalTitle}>Déplacer vers...</Text>
<TouchableOpacity
style={styles.folderOption}
onPress={() => handleMove(null)}
>
<MaterialIcons name="home" size={20} color="#666" />
<Text style={styles.folderOptionText}>Racine</Text>
</TouchableOpacity>
{(foldersData?.data ?? []).map((folder) => (
<TouchableOpacity
key={folder.id}
style={styles.folderOption}
onPress={() => handleMove(folder.id)}
>
<MaterialIcons name="folder" size={20} color="#F57C00" />
<Text style={styles.folderOptionText}>{folder.name}</Text>
</TouchableOpacity>
))}
</TouchableOpacity>
</TouchableOpacity>
</Modal>
</KeyboardAvoidingView>
);
}
@@ -590,6 +632,23 @@ const styles = StyleSheet.create({
borderColor: '#F57C00',
backgroundColor: 'transparent',
},
moveActionBtn: {
borderColor: '#00897B',
backgroundColor: 'transparent',
},
folderOption: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 12,
paddingHorizontal: 8,
gap: 10,
borderBottomWidth: 1,
borderBottomColor: '#f0f0f0',
},
folderOptionText: {
fontSize: 16,
color: '#333',
},
modalOverlay: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.4)',
+2
View File
@@ -5,6 +5,8 @@ export const ENDPOINTS = {
FILE: '/files',
UPLOAD: '/files/upload',
SEARCH: '/files/search',
MOVE: '/files/move',
FOLDERS: '/files/folders',
OCR_JOBS: '/ocr/jobs',
HEALTH: '/health',
} as const;
+19
View File
@@ -51,3 +51,22 @@ export function useAddTags() {
},
});
}
export function useMoveFiles() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ fileIds, parentFileId }: { fileIds: string[]; parentFileId: string | null }) =>
apiClient.post(ENDPOINTS.MOVE, { file_ids: fileIds, parent_file_id: parentFileId }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['files'] });
},
});
}
export function useFolders() {
return useQuery({
queryKey: ['folders'],
queryFn: () => apiClient.get<{ data: FileItem[] }>(ENDPOINTS.FOLDERS),
});
}