Files
web-frontend/app/pages/notifications.vue

144 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { useMutation, useQuery } from '@vue/apollo-composable';
import {
MyMessengerConnectionsDocument,
MyNotificationHistoryDocument,
SendTestMessengerMessageDocument,
} from '~/composables/graphql/generated';
const selectedChannel = ref<'TELEGRAM' | 'MAX'>('TELEGRAM');
const channelId = ref('');
const customMessage = ref('Тест канала уведомлений Fregat');
const feedback = ref('');
const connectionsQuery = useQuery(MyMessengerConnectionsDocument);
const historyQuery = useQuery(MyNotificationHistoryDocument, () => ({
channel: selectedChannel.value,
limit: 50,
}));
const sendTestMutation = useMutation(SendTestMessengerMessageDocument);
watch(selectedChannel, () => {
feedback.value = '';
historyQuery.refetch({
channel: selectedChannel.value,
limit: 50,
});
});
const activeConnection = computed(() =>
connectionsQuery.result.value?.myMessengerConnections?.find(
(item: { type: 'TELEGRAM' | 'MAX'; isActive: boolean; channelId: string }) =>
item.type === selectedChannel.value && item.isActive,
),
);
async function sendTest() {
feedback.value = '';
const result = await sendTestMutation.mutate({
type: selectedChannel.value,
channelId: channelId.value || undefined,
message: customMessage.value || undefined,
});
const payload = result?.data?.sendTestMessengerMessage;
if (!payload) {
feedback.value = 'Не удалось отправить тестовое сообщение.';
return;
}
feedback.value = payload.success
? `Отправлено в ${payload.type}: ${payload.detail}`
: `Ошибка отправки: ${payload.detail}`;
await historyQuery.refetch({
channel: selectedChannel.value,
limit: 50,
});
}
</script>
<template>
<section class="space-y-6">
<div>
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Уведомления</h1>
<p class="mt-1 text-sm text-[#28543f]/80">Управление Telegram и Max в едином стиле кабинета.</p>
</div>
<div class="surface-card rounded-3xl p-5">
<div class="space-y-4">
<div class="tabs tabs-boxed w-fit">
<button
class="tab"
:class="{ 'tab-active': selectedChannel === 'TELEGRAM' }"
@click="selectedChannel = 'TELEGRAM'"
>
Telegram
</button>
<button
class="tab"
:class="{ 'tab-active': selectedChannel === 'MAX' }"
@click="selectedChannel = 'MAX'"
>
Max
</button>
</div>
<p class="text-sm opacity-80">
Активный канал:
<span class="font-semibold">
{{ activeConnection ? activeConnection.channelId : 'не подключен' }}
</span>
</p>
<label class="form-control">
<span class="label-text">Канал (опционально)</span>
<input
v-model="channelId"
class="input input-bordered border-[#d0e8d8] bg-white/80"
placeholder="если пусто, берется активный подключенный канал"
>
</label>
<label class="form-control">
<span class="label-text">Тестовое сообщение</span>
<textarea v-model="customMessage" class="textarea textarea-bordered border-[#d0e8d8] bg-white/80" rows="3" />
</label>
<button
class="btn w-fit border-0 bg-[#139957] text-white hover:bg-[#0d854a]"
:disabled="sendTestMutation.loading.value"
@click="sendTest"
>
Отправить тест
</button>
<div v-if="feedback" class="alert" :class="feedback.startsWith('Ошибка') ? 'alert-error' : 'alert-success'">
{{ feedback }}
</div>
</div>
</div>
<div class="surface-card rounded-3xl p-5">
<div class="space-y-3">
<h2 class="text-xl font-bold text-[#123824]">История по каналу {{ selectedChannel }}</h2>
<div v-if="historyQuery.loading.value" class="alert border-0 bg-white/75">Загрузка истории...</div>
<div v-else-if="(historyQuery.result.value?.myNotificationHistory?.length ?? 0) === 0" class="alert">
История пока пустая.
</div>
<ul v-else class="space-y-3">
<li
v-for="item in historyQuery.result.value?.myNotificationHistory ?? []"
:key="item.id"
class="rounded-xl border border-[#d6ebde] bg-white/75 p-3"
>
<p class="font-semibold">{{ item.title }}</p>
<p class="text-sm opacity-80">{{ item.message }}</p>
<p class="text-xs opacity-60">{{ new Date(item.createdAt).toLocaleString() }}</p>
</li>
</ul>
</div>
</div>
</section>
</template>