80 lines
3.0 KiB
Vue
80 lines
3.0 KiB
Vue
<template>
|
|
<div v-if="documents.length" class="mt-3">
|
|
<p class="mb-2 text-sm font-medium text-neutral-700">
|
|
{{ $t('taskDocuments.title') }} ({{ documents.length }})
|
|
</p>
|
|
<div class="grid grid-cols-2 gap-2 sm:grid-cols-3">
|
|
<div
|
|
v-for="doc in documents"
|
|
:key="doc.id"
|
|
class="group relative flex cursor-pointer items-center gap-2 rounded-lg border border-neutral-200 p-2 transition-colors hover:bg-neutral-50"
|
|
@click="$emit('preview', doc)"
|
|
>
|
|
<!-- Thumbnail or icon -->
|
|
<div class="flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded">
|
|
<img
|
|
v-if="isImage(doc.mimeType)"
|
|
:src="getDownloadUrl(doc.id)"
|
|
:alt="doc.originalName"
|
|
class="h-10 w-10 object-cover"
|
|
/>
|
|
<Icon
|
|
v-else
|
|
:name="getIconForMime(doc.mimeType)"
|
|
class="h-6 w-6 text-neutral-400"
|
|
/>
|
|
</div>
|
|
|
|
<!-- File info -->
|
|
<div class="min-w-0 flex-1">
|
|
<p class="truncate text-xs font-medium text-neutral-700">{{ doc.originalName }}</p>
|
|
<p class="text-xs text-neutral-400">{{ formatSize(doc.size) }}</p>
|
|
</div>
|
|
|
|
<!-- Delete button -->
|
|
<button
|
|
v-if="isAdmin"
|
|
class="absolute right-1 top-1 hidden rounded p-0.5 text-neutral-400 transition-colors hover:bg-red-50 hover:text-red-500 group-hover:block"
|
|
@click.stop="$emit('delete', doc)"
|
|
>
|
|
<Icon name="heroicons:x-mark" class="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { TaskDocument } from '~/services/dto/task-document'
|
|
|
|
defineProps<{
|
|
documents: TaskDocument[]
|
|
isAdmin: boolean
|
|
}>()
|
|
|
|
defineEmits<{
|
|
preview: [doc: TaskDocument]
|
|
delete: [doc: TaskDocument]
|
|
}>()
|
|
|
|
const { getDownloadUrl } = useTaskDocumentService()
|
|
|
|
function isImage(mimeType: string): boolean {
|
|
return mimeType.startsWith('image/')
|
|
}
|
|
|
|
function getIconForMime(mimeType: string): string {
|
|
if (mimeType === 'application/pdf') return 'heroicons:document-text'
|
|
if (mimeType.includes('spreadsheet') || mimeType.includes('excel')) return 'heroicons:table-cells'
|
|
if (mimeType.includes('word') || mimeType.includes('document')) return 'heroicons:document'
|
|
if (mimeType.includes('zip') || mimeType.includes('archive') || mimeType.includes('tar') || mimeType.includes('rar')) return 'heroicons:archive-box'
|
|
return 'heroicons:paper-clip'
|
|
}
|
|
|
|
function formatSize(bytes: number): string {
|
|
if (bytes < 1024) return `${bytes} o`
|
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} Ko`
|
|
return `${(bytes / (1024 * 1024)).toFixed(1)} Mo`
|
|
}
|
|
</script>
|