Files
portal/app/resources/js/views/settings/ProfileTab.vue
T
Дмитрий 394663597f phase2(settings): SettingsView - 8 вкладок (4 реализованы, 4 placeholder)
- SettingsView (/settings): sidebar tabs-rail (md=3, 8 v-list-item с mdi-icon)
  + content-pane (md=9 v-card outlined min-height 480px). activeTab ref
  переключает рендер вкладки.

Реализованы:
- ProfileTab: avatar 80px + 5 form-fields (имя/email disabled/телефон/TZ/роль).
- SecurityTab: 3 cards (Пароль / 2FA включена + recovery codes + Отключить /
  Активные сессии 3 mock с Завершить-btn).
- ApiTab: API-ключ password+eye-toggle + Webhook (URL + signing secret HMAC).
  Текст про дедуп (tenant_id, source_crm_id) 24ч и антифрод по phone (§10.8.1).
- NotificationsTab: матрица 8x3 (events × channels) соответствует schema v8.7
  §4 users.notification_preferences JSONB. 8 событий (new_lead, duplicate_detected,
  low_balance, tariff_charge, reminder_due, manager_assigned, webhook_failed,
  monthly_report) × 3 канала (email/sms/in_app). + sound_enabled switch.

Placeholder:
- PlaceholderTab универсальный с props title/description + v-alert «В разработке».
- Используется для Проекты / Команда / Интеграции / Тихие часы.

Маршрут /settings (meta.layout=app, lazy-import) в router + web.php.
.gitleaks.toml: settings/*.vue в allowlist (фиктивный профиль).
cspell-words.txt: смыслово.

Vitest +8 (всего 98/98 за 8.42s):
- 8 nav-tabs + все названия + дефолт «Профиль» + Проекты → «В разработке» +
  Уведомления показывает «События × каналы» + 5 событий матрицы +
  Безопасность: 2FA + сессии + API: API-ключ + Signing secret HMAC.

Регресс: lint+type+format OK; vitest 98/98; vite build (SettingsView lazy-chunk;
main app-chunk 107.85KB); story:build 17/24 за 31.7s; Pest 48/48 за 5.03s.

CLAUDE.md v1.27->v1.28, реестр Открытых_вопросов v1.36->v1.37.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:51:41 +03:00

81 lines
3.1 KiB
Vue

<script setup lang="ts">
/**
* Settings → Профиль. Данные текущего user'а: имя, email, телефон, тайм-зона.
* Источник дизайна: liderra_v8_handoff/concepts/v8_settings.html секция #profile.
*
* MVP: form-fields без save (TODO: PATCH /api/me).
*/
import { ref } from 'vue';
const fullName = ref('Иван Петров');
const email = ref('ivan.petrov@example.ru');
const phone = ref('+7 (916) 871-23-45');
const timezone = ref('Europe/Moscow');
const role = ref('Владелец');
</script>
<template>
<div class="tab-content">
<h2 class="tab-title text-h6 mb-4">Профиль</h2>
<v-row class="profile-row">
<v-col cols="auto">
<v-avatar size="80" color="primary">
<span class="text-h5">ИП</span>
</v-avatar>
<v-btn variant="text" size="small" class="mt-2" prepend-icon="mdi-camera"> Сменить </v-btn>
</v-col>
<v-col>
<v-row dense>
<v-col cols="12" md="6">
<v-text-field v-model="fullName" label="Полное имя" variant="outlined" density="comfortable" />
</v-col>
<v-col cols="12" md="6">
<v-text-field
v-model="email"
label="Email"
type="email"
variant="outlined"
density="comfortable"
disabled
persistent-hint
hint="Email менять только через support — связан с авторизацией"
/>
</v-col>
<v-col cols="12" md="6">
<v-text-field v-model="phone" label="Телефон" variant="outlined" density="comfortable" />
</v-col>
<v-col cols="12" md="6">
<v-text-field
v-model="timezone"
label="Тайм-зона"
variant="outlined"
density="comfortable"
persistent-hint
hint="Используется в логах и напоминаниях"
/>
</v-col>
<v-col cols="12" md="6">
<v-text-field v-model="role" label="Роль" variant="outlined" density="comfortable" disabled />
</v-col>
</v-row>
<div class="d-flex ga-2 mt-4">
<v-btn color="primary" variant="flat">Сохранить</v-btn>
<v-btn variant="text">Отмена</v-btn>
</div>
</v-col>
</v-row>
</div>
</template>
<style scoped>
.tab-title {
font-variation-settings: 'opsz' 18;
letter-spacing: -0.005em;
}
.profile-row {
align-items: flex-start;
}
</style>