Files
web-frontend/app/pages/settings-sync.vue
2026-04-07 10:56:45 +07:00

118 lines
3.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 { useQuery } from '@vue/apollo-composable';
import {
IntegrationSyncDashboardDocument,
type IntegrationSyncDashboardQuery,
} from '~/composables/graphql/generated';
definePageMeta({
middleware: ['manager-only'],
path: '/admin/settings/sync',
});
type SyncItem = IntegrationSyncDashboardQuery['integrationSyncDashboard']['items'][number];
const syncDashboardQuery = useQuery(IntegrationSyncDashboardDocument);
const dashboard = computed(() => syncDashboardQuery.result.value?.integrationSyncDashboard ?? null);
const syncItems = computed<SyncItem[]>(() => dashboard.value?.items ?? []);
function itemIsHealthy(item: SyncItem) {
return item.syncedCount > 0 && Boolean(item.lastSyncedAt);
}
function statusLabel(item: SyncItem) {
return itemIsHealthy(item) ? 'Работает' : 'Нет данных';
}
function syncSummary(item: SyncItem) {
if (!item.syncedCount) {
return 'Данных пока нет.';
}
return `Загружено ${item.syncedCount} записей.`;
}
function formatDateTime(value?: string | null) {
if (!value) {
return 'Пока нет';
}
return new Date(value).toLocaleString('ru-RU', {
day: '2-digit',
month: 'short',
hour: '2-digit',
minute: '2-digit',
});
}
</script>
<template>
<section class="space-y-6">
<div class="space-y-2">
<h1 class="text-3xl font-extrabold text-[#0f2f20]">1С</h1>
<p class="text-sm leading-6 text-[#557562]">
Статус синхронизации по ключевым событиям.
</p>
</div>
<div v-if="syncDashboardQuery.loading.value" class="manager-empty-state">
Загружаем статусы...
</div>
<template v-else-if="dashboard">
<section class="space-y-4">
<article
v-for="item in syncItems"
:key="item.id"
class="rounded-[28px] bg-white p-5 shadow-[0_18px_38px_rgba(18,56,36,0.08)]"
>
<div class="flex flex-col gap-4 md:flex-row md:items-start md:justify-between">
<div class="min-w-0 space-y-3">
<div class="flex flex-wrap items-center gap-3">
<span
class="inline-flex items-center gap-2 rounded-full px-3 py-1 text-xs font-bold uppercase tracking-[0.12em]"
:class="itemIsHealthy(item) ? 'bg-[#e8f5ec] text-[#1c6b45]' : 'bg-[#fff1ec] text-[#b54b2f]'"
>
<span
class="h-2.5 w-2.5 rounded-full"
:class="itemIsHealthy(item) ? 'bg-[#1c6b45]' : 'bg-[#d76745]'"
/>
{{ statusLabel(item) }}
</span>
<span class="text-xs font-semibold uppercase tracking-[0.12em] text-[#6a8a76]">
{{ item.source }}
</span>
</div>
<div class="space-y-1">
<h2 class="text-xl font-bold text-[#123824]">{{ item.title }}</h2>
<p class="text-sm text-[#557562]">
Последний run: {{ formatDateTime(item.lastSyncedAt) }}
</p>
</div>
<p class="text-sm leading-6 text-[#123824]">
{{ syncSummary(item) }}
</p>
<p class="text-sm leading-6 text-[#557562]">
{{ item.note }}
</p>
</div>
<div class="rounded-[20px] bg-[#f7fbf8] px-4 py-3 text-left md:min-w-[180px] md:text-right">
<p class="text-xs font-semibold uppercase tracking-[0.12em] text-[#688676]">
Обновлений
</p>
<p class="mt-2 text-2xl font-black tracking-[-0.04em] text-[#123824]">
{{ item.syncedCount }}
</p>
</div>
</div>
</article>
</section>
</template>
</section>
</template>