224 lines
8.9 KiB
Vue
224 lines
8.9 KiB
Vue
<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 route = useRoute();
|
||
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 || ''));
|
||
const successChannel = computed(() => {
|
||
const raw = String(route.query.connected || '').trim().toLowerCase();
|
||
return raw === 'telegram' || raw === 'max' ? raw : '';
|
||
});
|
||
const showSuccess = computed(() => route.query.status === 'success' && Boolean(successChannel.value));
|
||
const profileName = computed(() => meQuery.result.value?.me?.fullName?.trim() || meQuery.result.value?.me?.email || 'Пользователь');
|
||
const profileInitials = computed(() =>
|
||
profileName.value
|
||
.split(' ')
|
||
.filter(Boolean)
|
||
.slice(0, 2)
|
||
.map((part) => part.charAt(0).toUpperCase())
|
||
.join('') || 'FR',
|
||
);
|
||
const successTitle = computed(() =>
|
||
successChannel.value === 'telegram' ? 'Telegram успешно подключен' : 'Max успешно подключен',
|
||
);
|
||
const successText = computed(() =>
|
||
successChannel.value === 'telegram'
|
||
? 'Теперь этот Telegram привязан к вашему кабинету, и уведомления будут приходить в него.'
|
||
: 'Теперь этот Max привязан к вашему кабинету, и уведомления будут приходить в него.',
|
||
);
|
||
const successConnection = computed(() =>
|
||
successChannel.value === 'telegram' ? telegramConnection.value : maxConnection.value,
|
||
);
|
||
const successAvatarSrc = computed(() => messengerConnectionAvatarSrc(successConnection.value));
|
||
const successAvatarInitials = computed(() =>
|
||
messengerConnectionInitials(
|
||
successConnection.value,
|
||
profileInitials.value,
|
||
),
|
||
);
|
||
const successConnectionName = computed(() => messengerConnectionName(successConnection.value));
|
||
const successConnectionHandleValue = computed(() => messengerConnectionHandle(successConnection.value));
|
||
|
||
onMounted(() => {
|
||
if (showSuccess.value) {
|
||
void connectionsQuery.refetch();
|
||
void meQuery.refetch();
|
||
}
|
||
});
|
||
|
||
async function connectMessenger(channel: 'TELEGRAM' | 'MAX') {
|
||
const baseUrl = channel === 'TELEGRAM' ? telegramConnectUrl.value : maxConnectUrl.value;
|
||
if (!baseUrl) {
|
||
return;
|
||
}
|
||
|
||
await openMessengerBot({
|
||
channel,
|
||
baseUrl,
|
||
redirectPath: `/profile/notifications?status=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 v-if="showSuccess" class="surface-card rounded-3xl border border-[#c7efd7] bg-[#f4fff8] p-5">
|
||
<div class="flex flex-col gap-4 md:flex-row md:items-center">
|
||
<div v-if="successAvatarSrc" class="avatar">
|
||
<div class="h-18 w-18 rounded-full ring ring-[#c7efd7] ring-offset-2 ring-offset-white">
|
||
<img :src="successAvatarSrc" :alt="successConnectionName">
|
||
</div>
|
||
</div>
|
||
<div v-else class="avatar placeholder">
|
||
<div class="h-18 w-18 rounded-full bg-[#123824] text-xl font-bold text-white">
|
||
<span>{{ successAvatarInitials }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="space-y-1">
|
||
<div class="badge badge-success badge-outline">Успешно</div>
|
||
<h2 class="text-2xl font-extrabold text-[#0f2f20]">{{ successTitle }}</h2>
|
||
<div class="flex flex-wrap items-center gap-2 text-sm text-[#355947]">
|
||
<span class="font-semibold text-[#123824]">{{ successConnectionName }}</span>
|
||
<span v-if="successConnectionHandleValue">{{ successConnectionHandleValue }}</span>
|
||
</div>
|
||
<p class="text-sm text-[#355947]">
|
||
{{ successText }}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="surface-card rounded-3xl p-5">
|
||
<p class="text-sm text-[#355947]">
|
||
Подключите Telegram и Max, чтобы получать статусы заказов и важные уведомления в удобном канале.
|
||
</p>
|
||
|
||
<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>
|