Feat: Validacion de tamaño de archivos y notificaciones de error
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m9s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m9s
- Agregar validacion de tamaño en frontend antes de enviar - Mostrar toast con error cuando archivo excede limite - Mostrar toast con mensaje de error del servidor cuando falla envio - Limites: imagen 16MB, video 64MB, audio 16MB, documento 100MB
This commit is contained in:
@@ -184,6 +184,16 @@ const caption = ref('')
|
||||
const isDragging = ref(false)
|
||||
const stickerModes = ref<boolean[]>([])
|
||||
|
||||
// File size limits (in bytes) - should match server
|
||||
const MAX_SIZES: Record<string, number> = {
|
||||
image: 16 * 1024 * 1024, // 16 MB
|
||||
video: 64 * 1024 * 1024, // 64 MB
|
||||
audio: 16 * 1024 * 1024, // 16 MB
|
||||
document: 100 * 1024 * 1024, // 100 MB
|
||||
}
|
||||
|
||||
const toast = useToast()
|
||||
|
||||
// Audio recorder
|
||||
const {
|
||||
isRecording,
|
||||
@@ -242,12 +252,48 @@ const handleFileSelect = (event: Event, type: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
const getFileMediaType = (file: File): string => {
|
||||
if (file.type.startsWith('image/')) return 'image'
|
||||
if (file.type.startsWith('video/')) return 'video'
|
||||
if (file.type.startsWith('audio/')) return 'audio'
|
||||
return 'document'
|
||||
}
|
||||
|
||||
const formatFileSize = (bytes: number): string => {
|
||||
if (bytes === 0) return '0 B'
|
||||
const k = 1024
|
||||
const sizes = ['B', 'KB', 'MB', 'GB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`
|
||||
}
|
||||
|
||||
const addFiles = (files: File[]) => {
|
||||
// Limit to 10 files
|
||||
const remaining = 10 - selectedFiles.value.length
|
||||
const toAdd = files.slice(0, remaining)
|
||||
// Use spread operator to trigger reactivity
|
||||
selectedFiles.value = [...selectedFiles.value, ...toAdd]
|
||||
|
||||
// Validate file sizes
|
||||
const validFiles: File[] = []
|
||||
for (const file of toAdd) {
|
||||
const mediaType = getFileMediaType(file)
|
||||
const maxSize = MAX_SIZES[mediaType]
|
||||
|
||||
if (file.size > maxSize) {
|
||||
toast.add({
|
||||
title: 'Archivo muy grande',
|
||||
description: `${file.name} (${formatFileSize(file.size)}) excede el límite de ${formatFileSize(maxSize)} para ${mediaType}`,
|
||||
color: 'error',
|
||||
duration: 5000
|
||||
})
|
||||
} else {
|
||||
validFiles.push(file)
|
||||
}
|
||||
}
|
||||
|
||||
if (validFiles.length > 0) {
|
||||
// Use spread operator to trigger reactivity
|
||||
selectedFiles.value = [...selectedFiles.value, ...validFiles]
|
||||
}
|
||||
}
|
||||
|
||||
const handleDrop = (event: DragEvent) => {
|
||||
|
||||
@@ -548,8 +548,23 @@ const handleSendMessage = async (content: string, files: File[], caption: string
|
||||
|
||||
// Reload messages
|
||||
messages.value = await $fetch(`/api/messages/${instanceId}/${chatId}`)
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
console.error('Error sending message:', e)
|
||||
|
||||
// Extract error message from response
|
||||
let errorMessage = 'Error al enviar el mensaje'
|
||||
if (e?.data?.message) {
|
||||
errorMessage = e.data.message
|
||||
} else if (e?.message) {
|
||||
errorMessage = e.message
|
||||
}
|
||||
|
||||
toast.add({
|
||||
title: 'Error de envío',
|
||||
description: errorMessage,
|
||||
color: 'error',
|
||||
duration: 5000
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user