Files
zyrarbot/frontend/src/components/UploadsPanel.vue
T
mmacierzanka 2a11c70a3e
Backend / Lint i formatowanie (push) Successful in 3s
Backend / Testy i kontrakt API (push) Successful in 5s
Panel / Lint, typy i build (push) Failing after 9s
Backend / Testowy build obrazu (push) Successful in 9s
feat: improve styles and layouts for better consistency and responsiveness
2026-08-21 21:29:57 +02:00

118 lines
2.9 KiB
Vue

<script setup lang="ts">
import { computed, ref } from 'vue'
import { FolderOpen, FolderUp, UploadCloud } from 'lucide-vue-next'
import UploadedFileRow from '@/components/UploadedFileRow.vue'
import { DASHBOARD_FILE_LIMIT, useUploads } from '@/composables/useUploads'
import { useToasts } from '@/composables/useToasts'
import { filesLabel } from '@/utils/plural'
import type { BotStatus } from '@/types/status'
const props = defineProps<{ status: BotStatus | null }>()
defineEmits<{ openLibrary: [] }>()
const { files, uploading, uploadLabel, upload, remove, enqueue } = useUploads()
const { notify } = useToasts()
const fileInput = ref<HTMLInputElement | null>(null)
const recent = computed(() => files.value.slice(0, DASHBOARD_FILE_LIMIT))
async function onFilesPicked(event: Event) {
const input = event.target as HTMLInputElement
if (input.files?.length) await upload(input.files)
input.value = ''
}
function play(filename: string) {
if (!props.status?.active_voice_channel) {
notify('Bot musi być połączony z kanałem głosowym!', 'error')
return
}
enqueue(filename)
}
</script>
<template>
<div class="glass-card uploads-panel">
<div class="queue-header">
<h2 class="card-title">
<FolderUp /> Serwerowa baza plików
</h2>
<span class="queue-count">{{ filesLabel(files.length) }}</span>
</div>
<div class="queue-list-container list-short">
<ul class="queue-list">
<UploadedFileRow
v-for="file in recent"
:key="file.filename"
:file="file"
@enqueue="play"
@remove="remove"
/>
<div
v-if="!files.length"
class="empty-queue-message"
>
<FolderOpen />
<p>Brak przesłanych plików na serwerze.</p>
</div>
</ul>
</div>
<div class="uploads-actions">
<input
ref="fileInput"
type="file"
hidden
multiple
accept=".aac,.avi,.flac,.flv,.m4a,.m4v,.mkv,.mov,.mp3,.mp4,.mpeg,.mpg,.oga,.ogg,.opus,.ts,.wav,.webm,.wma"
@change="onFilesPicked"
>
<button
class="btn btn-secondary"
:disabled="uploading"
@click="fileInput?.click()"
>
<UploadCloud /> Prześlij
</button>
<button
class="btn btn-secondary"
@click="$emit('openLibrary')"
>
<FolderOpen /> Wszystkie ({{ files.length }})
</button>
</div>
<div
v-if="uploading"
class="upload-progress"
>
<div class="progress-bar-bg">
<div class="progress-bar-fill indeterminate" />
</div>
<span class="time-text">{{ uploadLabel }}</span>
</div>
</div>
</template>
<style scoped>
.uploads-actions {
display: flex;
gap: 12px;
margin-top: 15px;
}
.uploads-actions .btn {
flex: 1;
}
.upload-progress {
margin-top: 10px;
text-align: center;
}
.upload-progress .time-text {
display: block;
margin-top: 4px;
}
</style>