Files
zyrarbot/frontend/src/components/VoiceChannelPanel.vue
T

131 lines
3.1 KiB
Vue

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { LogIn, LogOut, Radio } from 'lucide-vue-next'
import { api } from '@/api/client'
import { useToasts } from '@/composables/useToasts'
import type { BotStatus } from '@/types/status'
const props = defineProps<{ status: BotStatus | null }>()
const { notify, run } = useToasts()
const selected = ref('')
const defaultPlays = ref(5)
const channels = computed(() => props.status?.voice_channels ?? [])
const active = computed(() => props.status?.active_voice_channel ?? null)
// Wybór podąża za realnym połączeniem, a bez niego domyślnie wskazuje pierwszy kanał.
watch(
[active, channels],
([activeChannel, available]) => {
if (activeChannel) {
selected.value = activeChannel.channel_id
} else if (!available.some((channel) => channel.channel_id === selected.value)) {
selected.value = available[0]?.channel_id ?? ''
}
},
{ immediate: true },
)
watch(
() => props.status?.default_plays,
(value) => {
if (value !== undefined) defaultPlays.value = value
},
{ immediate: true },
)
async function toggle() {
if (active.value) {
await run(() => api.disconnect(), '', 'Błąd rozłączania')
return
}
if (!selected.value) {
notify('Wybierz kanał głosowy z listy!', 'error')
return
}
await run(() => api.connect(selected.value), '', 'Nie udało się połączyć')
}
async function saveDefaultPlays() {
await run(
() => api.setDefaultPlays(defaultPlays.value),
'Zapisano domyślną liczbę odtworzeń',
'Nie udało się zapisać domyślnej liczby odtworzeń',
)
}
</script>
<template>
<div class="glass-card connection-panel">
<h2 class="card-title">
<Radio /> Kanał Głosowy
</h2>
<div class="control-row">
<select
v-model="selected"
class="premium-select"
:disabled="!channels.length"
>
<option
v-if="!channels.length"
value=""
>
Brak dostępnych kanałów
</option>
<option
v-for="channel in channels"
:key="channel.channel_id"
:value="channel.channel_id"
>
{{ channel.channel_name }}
</option>
</select>
<button
class="btn"
:class="active ? 'btn-danger' : 'btn-primary btn-glow'"
@click="toggle"
>
<component :is="active ? LogOut : LogIn" />
{{ active ? 'Odłącz' : 'Połącz' }}
</button>
</div>
<div class="default-plays-row">
<label for="default-plays">Domyślny licznik</label>
<input
id="default-plays"
v-model.number="defaultPlays"
class="premium-input"
type="number"
min="1"
max="999"
>
<button
class="btn btn-secondary"
type="button"
@click="saveDefaultPlays"
>
Zapisz
</button>
</div>
</div>
</template>
<style scoped>
.default-plays-row {
display: flex;
align-items: center;
gap: 12px;
margin-top: 14px;
}
.default-plays-row label {
min-width: 130px;
color: var(--text-muted);
}
.default-plays-row .premium-input {
width: 90px;
}
</style>