# File Management Frontend System ## Overview Complete frontend file management system with Vue.js 3, TypeScript, and Pinia for state management. This system provides file upload, organization, filtering, and management capabilities. ## Architecture - **FileService**: API communication and data transformation - **FileStore**: Pinia store for state management - **TypeScript Interfaces**: Type safety for all data structures ## Installation The file service and store are ready to use. Import them in your components: ```typescript import { useFileStore } from "@/stores/fileStore"; import FileService from "@/services/file"; ``` ## FileStore Usage ### Basic Setup ```typescript import { useFileStore } from "@/stores/fileStore"; const fileStore = useFileStore(); // Reactive state const { files, isLoading, hasError, getError, getPagination, totalSizeFormatted, } = storeToRefs(fileStore); // Actions const { fetchFiles, uploadFile, deleteFile, searchFiles } = fileStore; ``` ### Store State Properties #### Files Management - `files` - Array of all files - `currentFile` - Currently selected/viewed file - `selectedFiles` - Array of selected file IDs for bulk operations - `filters` - Current filtering criteria - `pagination` - Pagination metadata #### Loading States - `loading` - General loading state - `uploadProgress` - Upload progress (0-100%) - `error` - Error message - `hasError` - Boolean error state #### Statistics - `organizedFiles` - Files grouped by category/subcategory - `storageStats` - Storage usage statistics ### Store Actions #### File Retrieval ```typescript // Get all files with pagination and filters await fileStore.fetchFiles({ page: 1, per_page: 15, search: "document", category: "devis", sort_by: "uploaded_at", sort_direction: "desc", }); // Get specific file by ID const file = await fileStore.fetchFile(123); // Search files await fileStore.searchFiles("invoice", { page: 1, per_page: 10 }); // Get files by category await fileStore.fetchFilesByCategory("devis", { per_page: 20 }); // Get files by client await fileStore.fetchFilesByClient(456, { per_page: 15 }); ``` #### File Upload ```typescript // Upload a single file const fileInput = ref(); const handleFileUpload = async (event: Event) => { const target = event.target as HTMLInputElement; const file = target.files?.[0]; if (file) { try { await fileStore.uploadFile({ file, category: "devis", client_id: 123, subcategory: "annual", description: "Annual quote document", tags: ["quote", "annual"], is_public: false, }); console.log("File uploaded successfully"); } catch (error) { console.error("Upload failed:", error); } } }; ``` #### File Management ```typescript // Update file metadata await fileStore.updateFile({ id: 123, file_name: "updated_filename.pdf", description: "Updated description", tags: ["updated", "tag"], category: "facture", }); // Delete single file await fileStore.deleteFile(123); // Delete multiple files await fileStore.deleteMultipleFiles([123, 124, 125]); // Download file await fileStore.downloadFile(123); // Generate download URL const downloadUrl = await fileStore.generateDownloadUrl(123); ``` #### Filtering and Organization ```typescript // Set filters fileStore.setFilters({ category: "devis", client_id: 123, date_from: "2024-01-01", date_to: "2024-12-31", mime_type: "application/pdf", }); // Clear filters fileStore.clearFilters(); // Get organized structure await fileStore.fetchOrganizedStructure(); // Get storage statistics await fileStore.fetchStorageStatistics(); ``` #### Selection Management ```typescript // Select/deselect files fileStore.selectFile(123); fileStore.deselectFile(123); // Select all/none fileStore.selectAllFiles(); fileStore.deselectAllFiles(); // Get selected files const selectedFiles = computed(() => fileStore.getSelectedFiles.value); ``` ### Computed Properties ```typescript // Basic getters const allFiles = computed(() => fileStore.allFiles); const isLoading = computed(() => fileStore.isLoading); const hasError = computed(() => fileStore.hasError); const totalSize = computed(() => fileStore.totalSizeFormatted); // Filtered views const imageFiles = computed(() => fileStore.imageFiles); const pdfFiles = computed(() => fileStore.pdfFiles); const recentFiles = computed(() => fileStore.recentFiles); // Grouped views const filesByCategory = computed(() => fileStore.filesByCategory); const filesByClient = computed(() => fileStore.filesByClient); // Pagination const pagination = computed(() => fileStore.getPagination); ``` ## FileService Usage ### Direct Service Methods ```typescript import FileService from "@/services/file"; // File validation before upload const validation = FileService.validateFile(file, 10 * 1024 * 1024); // 10MB if (!validation.valid) { console.error(validation.error); return; } // Format file size const sizeFormatted = FileService.formatFileSize(1024000); // "1000.00 KB" // Get file icon const icon = FileService.getFileIcon("application/pdf"); // "📄" // Check file type const isImage = FileService.isImageFile("image/jpeg"); // true const isPdf = FileService.isPdfFile("application/pdf"); // true // Get file extension const extension = FileService.getFileExtension("document.pdf"); // "pdf" ``` ## Component Examples ### File List Component ```vue ``` ### File Upload Component ```vue ``` ### File Statistics Component ```vue ``` ## Best Practices ### Error Handling ```typescript try { await fileStore.uploadFile(payload); // Success handling } catch (error: any) { // Display user-friendly error message const message = error.response?.data?.message || error.message; // Show in toast/notification } ``` ### File Validation ```typescript // Always validate files before upload const validation = FileService.validateFile(file); if (!validation.valid) { showError(validation.error); return; } ``` ### Progress Tracking ```vue ``` ### Bulk Operations ```typescript // Delete multiple files const deleteSelected = async () => { if (fileStore.selectedFiles.length === 0) return; if (confirm(`Supprimer ${fileStore.selectedFiles.length} fichiers ?`)) { await fileStore.deleteMultipleFiles(fileStore.selectedFiles); fileStore.deselectAllFiles(); } }; ``` ### Performance Optimization ```typescript // Use computed properties for filtered views const pdfFiles = computed(() => fileStore.pdfFiles); const imageFiles = computed(() => fileStore.imageFiles); // Cache expensive operations const fileStats = computed(() => { return { totalSize: fileStore.totalSizeFormatted, fileCount: fileStore.files.length, }; }); ``` ## Integration with Backend The frontend system integrates with the Laravel backend API through the FileService. All API endpoints are mapped: - `GET /api/files` → `FileService.getAllFiles()` - `POST /api/files` → `FileService.uploadFile()` - `GET /api/files/{id}` → `FileService.getFile()` - `PUT /api/files/{id}` → `FileService.updateFile()` - `DELETE /api/files/{id}` → `FileService.deleteFile()` - And specialized endpoints for categories, clients, statistics, etc. This ensures full compatibility with the backend file management system while providing a rich, type-safe frontend experience.