Files
BarangaySystem/resources/js/composables/useFileUpload.js
2026-06-06 18:43:00 +08:00

113 lines
3.4 KiB
JavaScript

import { ref } from 'vue';
import axios from 'axios';
/**
* Composable for handling file uploads.
*
* @param {Object} options
* @param {string[]} options.acceptedTypes - Array of accepted MIME types (default: ['image/*'])
* @param {number} options.maxSizeMB - Maximum file size in MB (default: 10)
* @param {string} options.category - Category for the upload (default: 'general')
*/
export function useFileUpload(options = {}) {
const acceptedTypes = options.acceptedTypes || ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
const maxSizeMB = options.maxSizeMB || 10;
const category = options.category || 'general';
const photoHashes = ref([]);
const isUploading = ref(false);
const uploadError = ref(null);
/**
* Upload a file to the server.
*
* @param {File} file
* @returns {Promise<Object|null>}
*/
const uploadFile = async (file) => {
// Validation
if (file.size > maxSizeMB * 1024 * 1024) {
uploadError.value = `File size exceeds ${maxSizeMB}MB limit.`;
return null;
}
const isAccepted = acceptedTypes.some(type => {
if (type.endsWith('/*')) {
const baseType = type.split('/')[0];
return file.type.startsWith(`${baseType}/`);
}
return file.type === type;
});
if (!isAccepted && acceptedTypes.length > 0) {
uploadError.value = 'Invalid file type.';
return null;
}
isUploading.value = true;
uploadError.value = null;
const formData = new FormData();
formData.append('file', file);
try {
const response = await axios.post(`/File/Upload/${category}`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
if (response.data && response.data.success && response.data.hashkey) {
const hashkey = response.data.hashkey;
photoHashes.value.push(hashkey);
return response.data;
} else {
throw new Error(response.data?.message || 'Upload failed');
}
} catch (err) {
console.error('Upload error:', err);
const status = err.response?.status;
const backendMsg = err.response?.data?.message || err.response?.data?.error;
if (status === 403) {
uploadError.value = "You don't have permission to upload files here.";
} else if (status === 413) {
uploadError.value = 'File too large.';
} else {
uploadError.value = backendMsg || err.message || 'Failed to upload file.';
}
return null;
} finally {
isUploading.value = false;
}
};
/**
* Remove a hash from the list.
*
* @param {string} hash
*/
const removeHash = (hash) => {
photoHashes.value = photoHashes.value.filter(h => h !== hash);
};
/**
* Set initial hashes (e.g., when loading existing data).
*
* @param {string[]} hashes
*/
const setInitialHashes = (hashes) => {
if (Array.isArray(hashes)) {
photoHashes.value = [...hashes];
}
};
return {
photoHashes,
isUploading,
uploadError,
uploadFile,
removeHash,
setInitialHashes
};
}