Files
web-frontend/app/pages/profile/notifications.vue
2026-04-06 14:41:32 +07:00

170 lines
6.7 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 { useQuery } from '@vue/apollo-composable';
import {
MeDocument,
MyMessengerConnectionsDocument,
} from '~/composables/graphql/generated';
import {
messengerConnectionAvatarSrc,
messengerConnectionHandle,
messengerConnectionInitials,
messengerConnectionName,
} from '~/composables/useMessengerConnectionPresentation';
import { useMessengerStart } from '~/composables/useMessengerStart';
type MessengerItem = {
id: string;
type: 'TELEGRAM' | 'MAX';
isActive: boolean;
channelId: string;
displayName?: string | null;
username?: string | null;
avatarAvailable?: boolean | null;
};
const config = useRuntimeConfig();
const meQuery = useQuery(MeDocument);
const connectionsQuery = useQuery(MyMessengerConnectionsDocument);
const { openMessengerBot, pendingChannel } = useMessengerStart();
const telegramConnection = computed(() =>
connectionsQuery.result.value?.myMessengerConnections?.find(
(item: MessengerItem) => item.type === 'TELEGRAM' && item.isActive,
),
);
const maxConnection = computed(() =>
connectionsQuery.result.value?.myMessengerConnections?.find(
(item: MessengerItem) => item.type === 'MAX' && item.isActive,
),
);
function buildBotConnectUrl(baseUrl: string) {
const accountEmail = meQuery.result.value?.me?.email?.trim().toLowerCase();
if (!accountEmail || !baseUrl) {
return '';
}
return baseUrl;
}
const telegramConnectUrl = computed(() => buildBotConnectUrl(config.public.telegramBotUrl || ''));
const maxConnectUrl = computed(() => buildBotConnectUrl(config.public.maxBotUrl || ''));
async function connectMessenger(channel: 'TELEGRAM' | 'MAX') {
const baseUrl = channel === 'TELEGRAM' ? telegramConnectUrl.value : maxConnectUrl.value;
if (!baseUrl) {
return;
}
await openMessengerBot({
channel,
baseUrl,
redirectPath: `/profile/notifications/success?connected=${channel.toLowerCase()}`,
});
}
</script>
<template>
<section class="space-y-6">
<NuxtLink to="/profile" class="link link-hover text-sm"> Назад в профиль</NuxtLink>
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Уведомления</h1>
<div class="surface-card rounded-3xl p-5">
<p class="text-sm text-[#355947]">
Подключите Telegram и Max, чтобы получать статусы заказов и важные уведомления в удобном канале.
</p>
<div class="mt-4 rounded-3xl border border-[#d6ebde] bg-[#f8fbf9] p-4">
<p class="text-sm font-semibold text-[#123824]">Бонусная программа теперь может жить в отдельном экране</p>
<p class="mt-2 text-sm leading-6 text-[#557562]">
Для бонусных начислений и выводов можно отправлять отдельное сообщение с кнопкой, которое ведёт в специальный бонусный интерфейс.
</p>
<div class="mt-3 flex flex-wrap gap-3">
<NuxtLink to="/messages" class="btn border-0 bg-[#111827] text-white hover:bg-[#000000]">
Message board
</NuxtLink>
<NuxtLink to="/bonus-program?entry=profile-notifications" class="btn btn-outline border-[#d7e9de] bg-white">
Открыть бонусный экран
</NuxtLink>
</div>
</div>
<div class="mt-4 space-y-3">
<div class="rounded-2xl bg-[#f8fbf9] p-4 transition hover:shadow-md">
<p class="font-semibold">Telegram</p>
<div v-if="telegramConnection" class="mt-3 flex items-center gap-3 rounded-2xl bg-white px-3 py-2">
<div v-if="messengerConnectionAvatarSrc(telegramConnection)" class="avatar">
<div class="h-11 w-11 rounded-full">
<img :src="messengerConnectionAvatarSrc(telegramConnection)" :alt="messengerConnectionName(telegramConnection)">
</div>
</div>
<div v-else class="avatar placeholder">
<div class="h-11 w-11 rounded-full bg-[#123824] text-sm font-bold text-white">
<span>{{ messengerConnectionInitials(telegramConnection, 'TG') }}</span>
</div>
</div>
<div class="min-w-0">
<p class="truncate text-sm font-semibold text-[#123824]">
{{ messengerConnectionName(telegramConnection) }}
</p>
<p class="truncate text-xs text-[#5c7b69]">
{{ messengerConnectionHandle(telegramConnection) || 'Подключен' }}
</p>
</div>
</div>
<p v-else class="text-sm opacity-80">Не подключен</p>
<button
class="btn btn-secondary mt-3 w-full"
:class="{ 'btn-disabled pointer-events-none': !telegramConnectUrl }"
:disabled="pendingChannel === 'TELEGRAM' || !telegramConnectUrl"
@click="connectMessenger('TELEGRAM')"
>
{{
pendingChannel === 'TELEGRAM'
? 'Открываем Telegram…'
: telegramConnection
? 'Переподключить Telegram'
: 'Подключить Telegram'
}}
</button>
</div>
<div class="rounded-2xl bg-[#f8fbf9] p-4 transition hover:shadow-md">
<p class="font-semibold">Max</p>
<div v-if="maxConnection" class="mt-3 flex items-center gap-3 rounded-2xl bg-white px-3 py-2">
<div class="avatar placeholder">
<div class="h-11 w-11 rounded-full bg-[#2b7fff] text-sm font-bold text-white">
<span>{{ messengerConnectionInitials(maxConnection, 'MX') }}</span>
</div>
</div>
<div class="min-w-0">
<p class="truncate text-sm font-semibold text-[#123824]">
{{ messengerConnectionName(maxConnection) }}
</p>
<p class="truncate text-xs text-[#5c7b69]">
{{ messengerConnectionHandle(maxConnection) || 'Подключен' }}
</p>
</div>
</div>
<p v-else class="text-sm opacity-80">Не подключен</p>
<button
class="btn btn-accent mt-3 w-full"
:class="{ 'btn-disabled pointer-events-none': !maxConnectUrl }"
:disabled="pendingChannel === 'MAX' || !maxConnectUrl"
@click="connectMessenger('MAX')"
>
{{
pendingChannel === 'MAX'
? 'Открываем Max…'
: maxConnection
? 'Переподключить Max'
: 'Подключить Max'
}}
</button>
</div>
</div>
</div>
</section>
</template>