initial: bootstrap from BukidBountyApp base
This commit is contained in:
112
resources/js/composables/useFileUpload.js
Normal file
112
resources/js/composables/useFileUpload.js
Normal file
@@ -0,0 +1,112 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user