1a0c9f5c8d
UI-аудит раунд 2 (Playwright, протыкивание форм): - vuetify.ts: +13 mdi→Lucide маппингов — bulk-бар проектов / импорт / экспорт отчётов и сделок / помощь / действия админки больше не падают в HelpCircle-fallback «?» - config/services.php + ErrorMeta/ErrorView/HelpView: support@liderra.app → support@liderra.ru (домен продукта .ru); status.liderra.app → status.liderra.ru - dealsApiMapper: ветка deal.commented — текст комментария в активности без служебного ключа «text:» - KanbanCard: costKopecks null-aware — «—» вместо врущего «0 ₽» (как в drawer) - DealsView: подзаголовок «crm.bp» → «crm.bp-gr.ru» (как в импорте/админке) Верификация: type-check ✓, build ✓, переоткрыто в Playwright локально (иконки/почта/комментарий/карточка/подзаголовок). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
110 lines
2.8 KiB
Vue
110 lines
2.8 KiB
Vue
<script setup lang="ts">
|
||
/**
|
||
* ErrorMeta — мета-блоки ErrorView: status-list (только для 500),
|
||
* RequestId/IncidentId с кнопкой копирования, и помощь-mailto (только 404).
|
||
*
|
||
* Sprint 4 Phase B/3 — split ErrorView (audit O-refactor-04 закрытие).
|
||
*/
|
||
defineProps<{
|
||
code: '404' | '403' | '500';
|
||
showStatusList?: boolean;
|
||
showRequestId?: boolean;
|
||
requestIdLabel?: string;
|
||
requestId?: string;
|
||
}>();
|
||
|
||
const statusList = [
|
||
{ name: 'API', status: 'ok' },
|
||
{ name: 'Telegram', status: 'degraded' },
|
||
{ name: 'YooKassa', status: 'ok' },
|
||
];
|
||
|
||
async function copyRequestId(id: string | undefined) {
|
||
if (id) {
|
||
await navigator.clipboard.writeText(id);
|
||
}
|
||
}
|
||
|
||
function statusColor(s: string): string {
|
||
return s === 'ok' ? '#2E8B57' : s === 'degraded' ? '#D9A441' : '#B83A3A';
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div v-if="showStatusList" class="status-list">
|
||
<span v-for="s in statusList" :key="s.name" class="status-item">
|
||
<span class="dot" :style="{ background: statusColor(s.status) }" />
|
||
{{ s.name }} ·
|
||
{{ s.status === 'ok' ? 'OK' : s.status === 'degraded' ? 'деградация' : 'недоступен' }}
|
||
</span>
|
||
</div>
|
||
|
||
<div v-if="showRequestId" class="err-id">
|
||
<span class="text-caption text-medium-emphasis">{{ requestIdLabel }}</span>
|
||
<span class="request-id">{{ requestId }}</span>
|
||
<v-btn
|
||
icon="mdi-content-copy"
|
||
variant="text"
|
||
size="x-small"
|
||
:aria-label="`Скопировать ID ${requestIdLabel}`"
|
||
@click="copyRequestId(requestId)"
|
||
/>
|
||
</div>
|
||
|
||
<p v-if="code === '404'" class="err-help text-caption">
|
||
Что-то не так? Напишите в
|
||
<a href="mailto:support@liderra.ru" class="err-help__link">support@liderra.ru</a>
|
||
</p>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.status-list {
|
||
display: flex;
|
||
gap: 16px;
|
||
margin-bottom: 16px;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
}
|
||
.status-item {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
font-size: 12px;
|
||
color: #b1c2bd;
|
||
font-family: 'JetBrains Mono', ui-monospace, monospace;
|
||
}
|
||
.status-item .dot {
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.err-id {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
background: rgba(255, 255, 255, 0.05);
|
||
padding: 6px 10px;
|
||
border-radius: 6px;
|
||
margin-bottom: 12px;
|
||
}
|
||
.request-id {
|
||
font-family: 'JetBrains Mono', ui-monospace, monospace;
|
||
font-size: 12px;
|
||
color: #fff;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.err-help {
|
||
color: #7a8c87;
|
||
margin-top: 16px;
|
||
}
|
||
.err-help__link {
|
||
color: #d3dad8;
|
||
text-decoration: underline;
|
||
}
|
||
.err-help__link:hover {
|
||
color: #ffffff;
|
||
}
|
||
</style>
|