1af9a093e7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
105 lines
3.9 KiB
Vue
105 lines
3.9 KiB
Vue
<script setup lang="ts">
|
|
/**
|
|
* Settings — настройки тенанта/пользователя. 4 рабочие вкладки.
|
|
*
|
|
* Источник дизайна: liderra_v8_handoff/concepts/v8_settings.html.
|
|
* Полностью реализованы (с UI-разводкой): Профиль, Безопасность, API и Webhook,
|
|
* Уведомления (матрица 8×3 по schema v8.7 §4 users.notification_preferences).
|
|
*
|
|
* Аудит D6/D7 (Sprint 3E, 2026-05-16): placeholder-вкладки Проекты/Команда/
|
|
* Интеграции/Тихие часы убраны — UI не должен обещать «в разработке».
|
|
* «Проекты» дублировали /projects; «Команда» и «Тихие часы» (ТЗ §17.8)
|
|
* требуют schema+backend (отдельные эпики); «Интеграции» внешне-блокированы (Б-1).
|
|
* Вкладки вернутся при реальной реализации соответствующих модулей.
|
|
*/
|
|
import { onMounted, ref } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
import ApiTab from './settings/ApiTab.vue';
|
|
import NotificationsTab from './settings/NotificationsTab.vue';
|
|
import ProfileTab from './settings/ProfileTab.vue';
|
|
import RequisitesTab from './settings/RequisitesTab.vue';
|
|
import SecurityTab from './settings/SecurityTab.vue';
|
|
|
|
interface Tab {
|
|
id: string;
|
|
label: string;
|
|
icon: string;
|
|
}
|
|
|
|
const tabs: Tab[] = [
|
|
{ id: 'profile', label: 'Профиль', icon: 'mdi-account-outline' },
|
|
{ id: 'requisites', label: 'Реквизиты', icon: 'mdi-file-document-outline' },
|
|
{ id: 'security', label: 'Безопасность', icon: 'mdi-shield-lock-outline' },
|
|
{ id: 'api', label: 'API и Webhook', icon: 'mdi-api' },
|
|
{ id: 'notifications', label: 'Уведомления', icon: 'mdi-bell-outline' },
|
|
];
|
|
|
|
const activeTab = ref('profile');
|
|
|
|
const route = useRoute();
|
|
onMounted(() => {
|
|
const t = route.query.tab;
|
|
if (typeof t === 'string' && tabs.some((tab) => tab.id === t)) {
|
|
activeTab.value = t;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<v-container fluid class="settings pa-6">
|
|
<header class="page-head">
|
|
<h1 class="text-h4 mb-2 page-title">Настройки</h1>
|
|
<p class="text-body-2 text-medium-emphasis ma-0">Профиль, безопасность, API и интеграции</p>
|
|
</header>
|
|
|
|
<v-row class="settings-row mt-4">
|
|
<v-col cols="12" md="3">
|
|
<v-card variant="outlined" class="tabs-rail pa-2">
|
|
<v-list density="compact" nav>
|
|
<v-list-item
|
|
v-for="tab in tabs"
|
|
:key="tab.id"
|
|
:prepend-icon="tab.icon"
|
|
:active="activeTab === tab.id"
|
|
rounded="lg"
|
|
@click="activeTab = tab.id"
|
|
>
|
|
<v-list-item-title>{{ tab.label }}</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-card>
|
|
</v-col>
|
|
|
|
<v-col cols="12" md="9">
|
|
<v-card variant="outlined" class="tab-pane pa-6">
|
|
<ProfileTab v-if="activeTab === 'profile'" />
|
|
<RequisitesTab v-else-if="activeTab === 'requisites'" />
|
|
<SecurityTab v-else-if="activeTab === 'security'" />
|
|
<ApiTab v-else-if="activeTab === 'api'" />
|
|
<NotificationsTab v-else-if="activeTab === 'notifications'" />
|
|
</v-card>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.settings {
|
|
max-width: 1440px;
|
|
}
|
|
|
|
.page-title {
|
|
font-variation-settings: 'opsz' 28;
|
|
letter-spacing: -0.018em;
|
|
}
|
|
|
|
.tabs-rail {
|
|
background: #fff;
|
|
}
|
|
|
|
.tab-pane {
|
|
background: #fff;
|
|
min-height: 480px;
|
|
}
|
|
</style>
|