feat: Initialize core application structure including authentication, role-based dashboards, service task management, and integration workflows.
This commit is contained in:
92
resources/js/Components/App/AttachmentSection.vue
Normal file
92
resources/js/Components/App/AttachmentSection.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<script setup>
|
||||
import { useForm } from '@inertiajs/vue3';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
attachments: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
taskId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
canManage: Boolean,
|
||||
});
|
||||
|
||||
const fileInput = ref(null);
|
||||
|
||||
const form = useForm({
|
||||
file: null,
|
||||
});
|
||||
|
||||
const uploadFile = () => {
|
||||
if (fileInput.value.files[0]) {
|
||||
form.file = fileInput.value.files[0];
|
||||
form.post(route('attachments.store', props.taskId), {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
form.reset();
|
||||
fileInput.value.value = '';
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const deleteAttachment = (id) => {
|
||||
if (confirm('Supprimer ce fichier ?')) {
|
||||
router.delete(route('attachments.destroy', id), {
|
||||
preserveScroll: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const formatSize = (bytes) => {
|
||||
if (!bytes) 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(2)) + ' ' + sizes[i];
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-4 border-t border-gray-100 dark:border-gray-700 pt-4">
|
||||
<h4 class="text-xs font-bold uppercase text-gray-400 mb-2">Pièces jointes ({{ attachments.length }})</h4>
|
||||
|
||||
<div class="space-y-2">
|
||||
<div v-for="file in attachments" :key="file.id" class="flex items-center justify-between p-2 bg-gray-50 dark:bg-gray-900/30 rounded border border-gray-100 dark:border-gray-700">
|
||||
<div class="flex items-center min-w-0">
|
||||
<svg class="w-4 h-4 text-gray-400 mr-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"></path></svg>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 truncate" :title="file.original_name">
|
||||
{{ file.original_name }}
|
||||
</span>
|
||||
<span class="ml-2 text-[10px] text-gray-400">({{ formatSize(file.size) }})</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3 ml-4">
|
||||
<a :href="route('attachments.download', file.id)" class="text-blue-500 hover:text-blue-700 text-xs font-bold">
|
||||
Télécharger
|
||||
</a>
|
||||
<button v-if="canManage" @click="deleteAttachment(file.id)" class="text-red-400 hover:text-red-600">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="attachments.length === 0" class="text-xs text-gray-500 italic">Aucun fichier joint.</div>
|
||||
|
||||
<div v-if="canManage" class="mt-4">
|
||||
<label class="block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1">Ajouter un fichier</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="file"
|
||||
ref="fileInput"
|
||||
@change="uploadFile"
|
||||
class="block w-full text-xs text-gray-500 file:mr-4 file:py-1 file:px-2 file:rounded-md file:border-0 file:text-xs file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100 dark:file:bg-gray-700 dark:file:text-gray-300"
|
||||
>
|
||||
<div v-if="form.processing" class="text-[10px] text-blue-500 animate-pulse">Upload...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user