Files
web-frontend/app/pages/profile/index.vue
2026-04-06 15:04:45 +07:00

145 lines
6.4 KiB
Vue
Raw Permalink 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 {
MyCounterpartyProfileDocument,
MyDeliveryAddressesDocument,
MyMessengerConnectionsDocument,
type MyDeliveryAddressesQuery,
} from '~/composables/graphql/generated';
import {
messengerConnectionAvatarSrc,
messengerConnectionHandle,
messengerConnectionInitials,
messengerConnectionName,
} from '~/composables/useMessengerConnectionPresentation';
import { isCounterpartyProfileComplete } from '~/composables/useCounterpartyProfile';
type MessengerItem = {
id: string;
type: 'TELEGRAM' | 'MAX';
channelId: string;
displayName?: string | null;
username?: string | null;
avatarAvailable?: boolean | null;
isActive: boolean;
};
type DeliveryAddressItem = MyDeliveryAddressesQuery['myDeliveryAddresses'][number];
const profileQuery = useQuery(MyCounterpartyProfileDocument);
const connectionsQuery = useQuery(MyMessengerConnectionsDocument);
const deliveryAddressesQuery = useQuery(MyDeliveryAddressesDocument);
const profileIsComplete = computed(() => isCounterpartyProfileComplete(profileQuery.result.value?.myCounterpartyProfile));
const telegramConnected = computed(() =>
connectionsQuery.result.value?.myMessengerConnections?.find(
(item: MessengerItem) => item.type === 'TELEGRAM' && item.isActive,
),
);
const maxConnected = computed(() =>
connectionsQuery.result.value?.myMessengerConnections?.find(
(item: MessengerItem) => item.type === 'MAX' && item.isActive,
),
);
const connectedMessengerCount = computed(() => Number(Boolean(telegramConnected.value)) + Number(Boolean(maxConnected.value)));
const companyNamePreview = computed(() => profileQuery.result.value?.myCounterpartyProfile?.companyName?.trim() || '');
const notificationsSummary = computed(() => {
if (connectedMessengerCount.value === 0) {
return 'Подключите Telegram и Max, чтобы получать статусы заказов и важные уведомления.';
}
if (connectedMessengerCount.value === 1) {
return 'Подключен один канал. Добавьте второй канал для резервного уведомления.';
}
return 'Оба канала подключены. Уведомления будут приходить в Telegram и Max.';
});
const deliveryAddresses = computed<DeliveryAddressItem[]>(() => deliveryAddressesQuery.result.value?.myDeliveryAddresses ?? []);
const defaultDeliveryAddress = computed(() => deliveryAddresses.value.find((item) => item.isDefault) ?? null);
</script>
<template>
<section class="space-y-6">
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Профиль</h1>
<div class="grid gap-4 md:grid-cols-3">
<NuxtLink
to="/profile/counterparty"
class="block rounded-3xl p-5 transition hover:shadow-md"
:class="profileIsComplete ? 'bg-white' : 'bg-[#fff8e6]'"
>
<div class="mb-2 flex items-start justify-between gap-2">
<p class="text-lg font-bold text-[#123824]">Карточка контрагента</p>
<span v-if="!profileIsComplete" class="text-[#b37a00]" aria-hidden="true"></span>
</div>
<p class="text-sm text-[#355947]">
{{
profileIsComplete
? `Компания: ${companyNamePreview || 'данные сохранены'}`
: 'Пожалуйста, заполните карточку контрагента, чтобы получить максимум возможностей личного кабинета.'
}}
</p>
</NuxtLink>
<NuxtLink to="/profile/notifications" class="block rounded-3xl bg-white p-5 transition hover:shadow-md">
<div class="mb-2 flex items-center justify-between gap-2">
<p class="text-lg font-bold text-[#123824]">Уведомления</p>
</div>
<div class="mb-3 space-y-2">
<div v-if="telegramConnected" class="flex items-center gap-3 rounded-2xl bg-[#f8fbf9] px-3 py-2">
<div v-if="messengerConnectionAvatarSrc(telegramConnected)" class="avatar">
<div class="h-10 w-10 rounded-full">
<img :src="messengerConnectionAvatarSrc(telegramConnected)" :alt="messengerConnectionName(telegramConnected)">
</div>
</div>
<div v-else class="avatar placeholder">
<div class="h-10 w-10 rounded-full bg-[#123824] text-xs font-bold text-white">
<span>{{ messengerConnectionInitials(telegramConnected, 'TG') }}</span>
</div>
</div>
<div class="min-w-0">
<p class="truncate text-sm font-semibold text-[#123824]">
{{ messengerConnectionName(telegramConnected) }}
</p>
<p class="truncate text-xs text-[#5c7b69]">
{{ messengerConnectionHandle(telegramConnected) || 'Telegram подключен' }}
</p>
</div>
</div>
<div v-if="maxConnected" class="flex items-center gap-3 rounded-2xl bg-[#f8fbf9] px-3 py-2">
<div class="avatar placeholder">
<div class="h-10 w-10 rounded-full bg-[#2b7fff] text-xs font-bold text-white">
<span>{{ messengerConnectionInitials(maxConnected, 'MX') }}</span>
</div>
</div>
<div class="min-w-0">
<p class="truncate text-sm font-semibold text-[#123824]">
{{ messengerConnectionName(maxConnected) }}
</p>
<p class="truncate text-xs text-[#5c7b69]">
{{ messengerConnectionHandle(maxConnected) || 'Max подключен' }}
</p>
</div>
</div>
</div>
<p class="text-sm text-[#355947]">{{ notificationsSummary }}</p>
</NuxtLink>
<NuxtLink to="/profile/addresses" class="block rounded-3xl bg-white p-5 transition hover:shadow-md">
<p class="mb-2 text-lg font-bold text-[#123824]">Адреса доставки</p>
<p class="text-sm text-[#355947]">
{{
defaultDeliveryAddress
? `Основной: ${defaultDeliveryAddress.label || defaultDeliveryAddress.address}`
: 'Добавьте первый адрес доставки, чтобы быстро оформлять заказы в корзине.'
}}
</p>
</NuxtLink>
</div>
</section>
</template>