feat: ajout de la fonctionnalité de conversion de fichiers CBR en CBZ, intégration d'un nouveau store pour gérer l'état de conversion, création de composants Vue pour l'upload de fichiers et le suivi de la progression, ainsi que la mise à jour de l'API pour gérer les conversions. Amélioration de la documentation API pour inclure les nouveaux endpoints et formats de fichiers supportés.
This commit is contained in:
parent
7a05934116
commit
d9e78b5229
@@ -0,0 +1,214 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative"
|
||||
@dragover.prevent="handleDragOver"
|
||||
@dragenter.prevent="handleDragEnter"
|
||||
@dragleave.prevent="handleDragLeave"
|
||||
@drop.prevent="handleDrop"
|
||||
>
|
||||
<div
|
||||
:class="[
|
||||
'border-2 border-dashed rounded-lg p-8 text-center transition-all duration-200',
|
||||
isDragOver
|
||||
? 'border-green-400 bg-green-50'
|
||||
: 'border-gray-300 hover:border-gray-400'
|
||||
]"
|
||||
>
|
||||
<!-- Zone d'upload -->
|
||||
<div class="space-y-4">
|
||||
<!-- Icône -->
|
||||
<div class="flex justify-center">
|
||||
<ArchiveBoxIcon
|
||||
:class="[
|
||||
'w-16 h-16 transition-colors duration-200',
|
||||
isDragOver ? 'text-green-500' : 'text-gray-400'
|
||||
]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Message principal -->
|
||||
<div class="space-y-2">
|
||||
<h3 class="text-lg font-medium text-gray-900">
|
||||
{{ isDragOver ? 'Déposez votre fichier ici' : 'Sélectionnez un fichier CBR ou CBZ' }}
|
||||
</h3>
|
||||
<p class="text-sm text-gray-500">
|
||||
Glissez-déposez votre fichier ou cliquez pour le sélectionner
|
||||
</p>
|
||||
<p class="text-xs text-gray-400">
|
||||
Fichiers supportés: .cbr, .cbz (max. 150MB)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Bouton de sélection -->
|
||||
<div class="flex justify-center">
|
||||
<label
|
||||
for="file-upload"
|
||||
:class="[
|
||||
'relative cursor-pointer rounded-md px-4 py-2 font-medium text-white transition-colors duration-200',
|
||||
isDragOver
|
||||
? 'bg-green-500 hover:bg-green-600'
|
||||
: 'bg-green-600 hover:bg-green-700'
|
||||
]"
|
||||
>
|
||||
<span>Sélectionner un fichier</span>
|
||||
<input
|
||||
id="file-upload"
|
||||
name="file-upload"
|
||||
type="file"
|
||||
class="sr-only"
|
||||
accept=".cbr,.cbz"
|
||||
@change="handleFileSelect"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Informations du fichier sélectionné -->
|
||||
<div v-if="selectedFile" class="mt-6 p-4 bg-gray-50 rounded-lg">
|
||||
<div class="flex items-center space-x-3">
|
||||
<DocumentIcon class="w-8 h-8 text-gray-600" />
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-medium text-gray-900 truncate">
|
||||
{{ selectedFile.name }}
|
||||
</p>
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ formatFileSize(selectedFile.size) }}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@click="clearFile"
|
||||
class="p-1 text-gray-400 hover:text-gray-600 transition-colors"
|
||||
title="Supprimer le fichier"
|
||||
>
|
||||
<XMarkIcon class="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Overlay pendant le drag -->
|
||||
<div
|
||||
v-if="isDragOver"
|
||||
class="absolute inset-0 bg-green-100 bg-opacity-50 rounded-lg flex items-center justify-center"
|
||||
style="pointer-events: none;"
|
||||
>
|
||||
<div class="text-green-600 font-medium text-lg">
|
||||
Déposez le fichier ici
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArchiveBoxIcon, DocumentIcon, XMarkIcon } from '@heroicons/vue/24/outline';
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
name: 'FileUploadArea',
|
||||
|
||||
components: {
|
||||
ArchiveBoxIcon,
|
||||
DocumentIcon,
|
||||
XMarkIcon,
|
||||
},
|
||||
|
||||
props: {
|
||||
selectedFile: {
|
||||
type: File,
|
||||
default: null,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['file-selected', 'file-cleared'],
|
||||
|
||||
setup(props, { emit }) {
|
||||
const isDragOver = ref(false);
|
||||
const dragCounter = ref(0);
|
||||
|
||||
// Handlers pour le drag & drop
|
||||
const handleDragEnter = (event) => {
|
||||
if (props.disabled) return;
|
||||
|
||||
event.preventDefault();
|
||||
dragCounter.value++;
|
||||
isDragOver.value = true;
|
||||
};
|
||||
|
||||
const handleDragOver = (event) => {
|
||||
if (props.disabled) return;
|
||||
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const handleDragLeave = (event) => {
|
||||
if (props.disabled) return;
|
||||
|
||||
event.preventDefault();
|
||||
dragCounter.value--;
|
||||
|
||||
if (dragCounter.value === 0) {
|
||||
isDragOver.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDrop = (event) => {
|
||||
if (props.disabled) return;
|
||||
|
||||
event.preventDefault();
|
||||
isDragOver.value = false;
|
||||
dragCounter.value = 0;
|
||||
|
||||
const files = event.dataTransfer.files;
|
||||
if (files.length > 0) {
|
||||
const file = files[0];
|
||||
emit('file-selected', file);
|
||||
}
|
||||
};
|
||||
|
||||
// Handler pour la sélection de fichier via input
|
||||
const handleFileSelect = (event) => {
|
||||
if (props.disabled) return;
|
||||
|
||||
const files = event.target.files;
|
||||
if (files.length > 0) {
|
||||
const file = files[0];
|
||||
emit('file-selected', file);
|
||||
}
|
||||
|
||||
// Réinitialiser l'input pour permettre la sélection du même fichier
|
||||
event.target.value = '';
|
||||
};
|
||||
|
||||
// Supprimer le fichier sélectionné
|
||||
const clearFile = () => {
|
||||
emit('file-cleared');
|
||||
};
|
||||
|
||||
// Formater la taille du fichier
|
||||
const formatFileSize = (bytes) => {
|
||||
if (bytes === 0) return '0 octets';
|
||||
|
||||
const k = 1024;
|
||||
const sizes = ['octets', 'Ko', 'Mo', 'Go'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
||||
};
|
||||
|
||||
return {
|
||||
isDragOver,
|
||||
handleDragEnter,
|
||||
handleDragOver,
|
||||
handleDragLeave,
|
||||
handleDrop,
|
||||
handleFileSelect,
|
||||
clearFile,
|
||||
formatFileSize,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user