SHiNE-server/shine-UI/js/mock-data.js
2026-06-19 19:48:26 +03:00

399 lines
20 KiB
JavaScript
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.

export const profile = {
login: '@shine.alex',
name: '',
avatarInitials: 'АС',
phone: '+7 (916) 221-45-88',
address: 'Москва, Пресненская наб., 12',
email: 'alex.shine@demo.local',
socials: '@alexshine / t.me/alexshine',
badges: ['Официальный аккаунт', 'Сияющий'],
};
export const wallet = {
balanceSOL: '182.4571',
publicAddress: '9sVAXJ2CqP3BrtC6AFeQHhcuWjN1kUyhY7L8pkQJxMZe',
updatedAt: 'сегодня, 14:42',
};
export const deviceSessions = [
{
sessionId: 'sess_7c5e5c4b',
clientInfoFromClient: 'Android 15; Pixel 9',
clientInfoFromRequest: 'UA=Java-http-client/17.0.18; remote=127.0.0.1',
geo: 'RU/Moscow',
lastAuthenticatedAtMs: 1774600010500,
},
{
sessionId: 'sess_90ab11de',
clientInfoFromClient: 'iOS 19; iPhone 17',
clientInfoFromRequest: 'UA=ShineMobile/2.4; remote=10.0.2.12',
geo: 'RU/Moscow',
lastAuthenticatedAtMs: 1774553310000,
},
{
sessionId: 'sess_3ea4f11c',
clientInfoFromClient: 'Windows 11; Chrome 124',
clientInfoFromRequest: 'UA=Mozilla/5.0; remote=192.168.1.21',
geo: 'RU/Kazan',
lastAuthenticatedAtMs: 1774499010000,
},
];
// Экран «Личные сообщения» — списочная форма «Связей». Храним СЕМАНТИКУ, не цвет.
// Цвет/режим вычисляет js/pages/messages/dm-visual-resolver.js (resolveDmVisualState):
// relationType: 'contact' | 'friend' | 'family' (family → золотой обод)
// relationRole: 'parent'|'child'|'sibling'|'spouse'|null
// isShining: true → небесный (celestial) обод/свечение (важнее relationType)
// isConfirmed: true → статус доверия «Подтверждён» (золотой shield) — НЕ красит обод
// hasActiveLink: true → статус «Связь» (изумруд) — приоритетнее «Подтверждён»
// unreadCount: number; preview: string
// toneOverride: 'default'|'family'|'shining' — ТОЛЬКО для тестового мока, в проде не использовать
// (на проде поля придут из relationFlagsForTarget/shineConfirmed/shine — пока мок для оффлайн-демо)
// ЛС-демо (мок). Поля СЕМАНТИЧЕСКИЕ (без хранения цвета) — визуал решает dm-visual-resolver.js.
// Набор покрывает ровно матрицу состояний M01M06 из спеки (по одному кейсу на строку).
export const directMessages = [
// M01 — обычный контакт, подтверждён: violet-обод, справа золотой shield «Подтверждён», без unread.
{ id: 'u1', name: 'Марина К.', initials: 'МК', preview: 'Вечером скину обновления по макетам.', lastMessage: 'Вечером скину обновления по макетам.', time: '15:08', relationType: 'contact', relationRole: null, isShining: false, isConfirmed: true, hasActiveLink: false, unreadCount: 0, photo: '/assets/demo-avatars/u1.jpg' },
// M02 — обычная активная связь: violet-обод, изумрудная капсула «Связь», отдельная violet-сфера «2».
{ id: 'u2', login: 'ilya', name: 'Илья П.', initials: 'ИП', preview: 'Спасибо, уже проверяю!', lastMessage: 'Спасибо, уже проверяю!', time: '14:31', relationType: 'contact', relationRole: null, isShining: false, isConfirmed: false, hasActiveLink: true, unreadCount: 2, photo: '/assets/demo-avatars/u2.jpg', connectedVia: [{ login: 'pavel', name: 'Павел С.', photo: '/assets/demo-avatars/u6.jpg' }] },
// M03 — сияющий с активной связью: мини-сфера языка «Связи», изумруд «Связь», violet-сфера «5».
{ id: 'u3', login: 'elena', name: 'Елена Д.', initials: 'ЕД', preview: 'Тестовый стенд снова доступен.', lastMessage: 'Тестовый стенд снова доступен.', time: '13:02', relationType: 'contact', relationRole: null, isShining: true, isConfirmed: false, hasActiveLink: true, unreadCount: 5, photo: '/assets/demo-avatars/u3.jpg', connectedVia: [{ login: 'pavel', name: 'Павел С.', photo: '/assets/demo-avatars/u6.jpg' }, { login: 'marina', name: 'Марина К.', photo: '/assets/demo-avatars/u1.jpg' }] },
// M04 — обычный контакт без статуса: только violet-обод и спокойный chevron, без unread.
{ id: 'u4', name: 'Никита О.', initials: 'НО', preview: 'Отлично, давай так и сделаем.', lastMessage: 'Отлично, давай так и сделаем.', time: 'вчера', relationType: 'contact', relationRole: null, isShining: false, isConfirmed: false, hasActiveLink: false, unreadCount: 0, photo: '/assets/demo-avatars/u4.jpg' },
// M05 — семья с подтверждением: золотой обод + тёплая аура, справа золотой shield «Подтверждён».
{ id: 'u6', name: 'Павел С.', initials: 'ПС', preview: 'Семейный архив обновил.', lastMessage: 'Семейный архив обновил.', time: 'вчера', relationType: 'family', relationRole: 'parent', isShining: false, isConfirmed: true, hasActiveLink: false, unreadCount: 0, photo: '/assets/demo-avatars/u6.jpg' },
// M06 — семья с активной связью: золотой обод (family), справа «Связь» по приоритету link>confirmed, violet-сфера «1».
{ id: 'u7', login: 'anya', name: 'Аня В.', initials: 'АВ', preview: 'Семейный чат: жду в 19:00.', lastMessage: 'Семейный чат: жду в 19:00.', time: 'пн', relationType: 'family', relationRole: 'sibling', isShining: false, isConfirmed: true, hasActiveLink: true, unreadCount: 1, photo: '/assets/demo-avatars/u7.jpg', connectedVia: [{ login: 'marina', name: 'Марина К.', photo: '/assets/demo-avatars/u1.jpg' }] },
];
export const contactDirectory = [
{
id: 'u5',
name: 'Марк С.',
initials: 'МС',
about: 'Продуктовый аналитик, любит короткие созвоны и длинные отчёты.',
},
{
id: 'u6',
name: 'Мария Л.',
initials: 'МЛ',
about: 'UI-дизайнер, собирает референсы и следит за визуальным стилем.',
},
{
id: 'u7',
name: 'Марина Р.',
initials: 'МР',
about: 'Контент-менеджер, ведёт каналы и готовит анонсы.',
},
{
id: 'u8',
name: 'Максим В.',
initials: 'МВ',
about: 'Frontend-разработчик, отвечает за анимации и адаптивность.',
},
{
id: 'u9',
name: 'Мадина А.',
initials: 'МА',
about: 'Комьюнити-менеджер, быстро находит нужных людей.',
},
{
id: 'u10',
name: 'Ирина П.',
initials: 'ИП',
about: 'Редактор новостей, помогает с текстами и публикациями.',
},
{
id: 'u11',
name: 'Николай Д.',
initials: 'НД',
about: 'Технический писатель, структурирует знания по продукту.',
},
{
id: 'u12',
name: 'Егор Т.',
initials: 'ЕТ',
about: 'QA-инженер, любит проверять сложные сценарии вручную.',
},
];
export const chatMessages = {
u1: [
{ from: 'in', text: 'Привет! Видел новые карточки?' },
{ from: 'out', text: 'Да, смотрятся сильно. Нужен финальный текст.' },
{ from: 'in', text: 'Вечером скину обновления по макетам.' },
],
u2: [
{ from: 'out', text: 'Скинул доступы в чат команды.' },
{ from: 'in', text: 'Спасибо, уже проверяю!' },
],
u3: [
{ from: 'in', text: 'Тестовый стенд снова доступен.' },
{ from: 'out', text: 'Отлично, запускаю прогон сценариев.' },
],
u4: [
{ from: 'in', text: 'Подтверждаю план на завтра.' },
{ from: 'out', text: 'Отлично, давай так и сделаем.' },
],
};
export const channels = [
{
id: 'ch0',
name: 'Личный канал',
initials: 'ЛК',
ownerLogin: '@shine.alex',
ownerName: 'Вы',
description: 'Ваш основной канал (нулевой).',
lastMessage: 'Добро пожаловать в личный канал.',
time: '16:05',
messagesCount: 14,
kind: 'own-personal',
},
{
id: 'ch1',
name: 'Команда продукта',
initials: 'КП',
ownerLogin: '@shine.alex',
ownerName: 'Вы',
description: 'Канал команды, который вы создали.',
lastMessage: 'Обновили roadmap на апрель.',
time: '15:42',
messagesCount: 8,
kind: 'own',
},
{
id: 'ch2',
name: 'Новости Bob',
initials: 'NB',
ownerLogin: '@bob',
ownerName: 'Bob',
description: 'Основной канал пользователя Bob.',
lastMessage: 'Вышел новый дайджест разработчика.',
time: '15:20',
messagesCount: 5,
kind: 'followed-user-channel',
},
{
id: 'ch3',
name: 'Стендап команды Bob',
initials: 'SB',
ownerLogin: '@bob',
ownerName: 'Bob',
description: 'Второй канал пользователя Bob.',
lastMessage: 'Перенесли созвон на 19:30.',
time: 'вчера',
messagesCount: 11,
kind: 'followed-user-channel',
},
{
id: 'ch4',
name: 'Анекдоты дня',
initials: 'АД',
ownerLogin: '@fun.club',
ownerName: 'Fun Club',
description: 'Публичный развлекательный канал по подписке.',
lastMessage: 'Сегодня в выпуске 5 новых шуток.',
time: 'вчера',
messagesCount: 33,
kind: 'subscribed',
},
];
export const channelPosts = {
ch0: [
{
id: 'p0-1',
title: 'Первый личный пост',
body: 'Этот канал всегда ваш и стоит в списке первым.',
},
{
id: 'p0-2',
title: 'Планы',
body: 'Сюда удобно сохранять личные заметки и объявления.',
},
],
ch1: [
{
id: 'p1',
title: 'Новый экран профиля',
body: 'Добавлены бейджи статуса, переработан верхний блок и улучшены быстрые переходы.',
},
{
id: 'p2',
title: 'Навигация без перезагрузки',
body: 'Переходы между экранами теперь стабильнее работают в SPA-режиме через hash-router.',
},
],
ch2: [
{
id: 'p3',
title: 'Анекдот утра',
body: 'Разработчик говорит: "Я починил один баг". Баги в ответ: "Нас было трое".',
},
{
id: 'p4',
title: 'Анекдот про дедлайн',
body: 'Дедлайн был настолько близко, что команда начала здороваться с ним по имени.',
},
],
ch3: [
{
id: 'p5',
title: 'Утренний дайджест',
body: 'Собрали ключевые новости дня: обновления продуктов, движения рынка и заметные релизы.',
},
{
id: 'p6',
title: 'Что обсуждают сегодня',
body: 'В фокусе дня: рост интереса к мобильным dApp-интерфейсам и новые анонсы сообществ.',
},
],
};
export const notifications = {
replies: [
{ id: 'r1', title: 'Марина К. ответила на ваш комментарий', text: 'Согласна, такую структуру и оставим.', time: '12 минут назад' },
{ id: 'r2', title: 'Илья П. ответил в обсуждении', text: 'Добавил примеры экранов для onboarding.', time: '48 минут назад' },
],
events: [
{ id: 'e1', title: 'Елена Д. добавила вас в друзья', text: 'Теперь вы в связях первого уровня.', time: 'сегодня' },
{ id: 'e2', title: 'Никита О. удалил из друзей', text: 'Связь перенесена в архив событий.', time: 'вчера' },
{ id: 'e3', title: 'Марина К. поставила лайк', text: 'Оценен ваш пост о прототипе.', time: '2 дня назад' },
],
};
export const networkGraph = {
center: { id: 'me', name: 'Вы', initials: 'ВЫ', x: 50, y: 50 },
peers: [
{ id: 'p1', name: 'Марина', initials: 'МК', x: 20, y: 24 },
{ id: 'p2', name: 'Илья', initials: 'ИП', x: 80, y: 22 },
{ id: 'p3', name: 'Елена', initials: 'ЕД', x: 18, y: 78 },
{ id: 'p4', name: 'Никита', initials: 'НО', x: 82, y: 76 },
],
};
// Мок интерактивной карты связей в форме ТЗ (focusUser + connections[]).
// Используется лабораторным режимом `network-view/lab` для проверки физики/центрирования.
// relationType: family | friend | business | contact; connectionStrength: 0..1 (сильнее → ближе к центру);
// status: 'shining' даёт эффект свечения; hasOwnConnections — есть ли у узла свои связи (для глубины).
export const networkGraphMock = {
focusUser: { id: 'u_100', login: 'ivan', name: 'Иван', avatar: 'url_to_image', status: 'shining' },
connections: [
{ id: 'u_101', login: 'alisa', name: 'Алиса', avatar: 'url_to_image', relationType: 'family', connectionStrength: 0.95, hasOwnConnections: true, status: 'shining' },
{ id: 'u_102', login: 'pavel', name: 'Павел', avatar: 'url_to_image', relationType: 'business', connectionStrength: 0.45, hasOwnConnections: false },
{ id: 'u_103', login: 'marina', name: 'Марина', avatar: 'url_to_image', relationType: 'friend', connectionStrength: 0.8, hasOwnConnections: true },
{ id: 'u_104', login: 'ilya', name: 'Илья', avatar: 'url_to_image', relationType: 'friend', connectionStrength: 0.6, hasOwnConnections: true },
{ id: 'u_105', login: 'elena', name: 'Елена', avatar: 'url_to_image', relationType: 'family', connectionStrength: 0.88, hasOwnConnections: false },
{ id: 'u_106', login: 'nikita', name: 'Никита', avatar: 'url_to_image', relationType: 'contact', connectionStrength: 0.3, hasOwnConnections: false },
{ id: 'u_107', login: 'oleg', name: 'Олег', avatar: 'url_to_image', relationType: 'business', connectionStrength: 0.55, hasOwnConnections: true, status: 'shining' },
{ id: 'u_108', login: 'sveta', name: 'Света', avatar: 'url_to_image', relationType: 'friend', connectionStrength: 0.7, hasOwnConnections: false },
{ id: 'u_109', login: 'dmitry', name: 'Дмитрий', avatar: 'url_to_image', relationType: 'contact', connectionStrength: 0.4, hasOwnConnections: true },
{ id: 'u_110', login: 'anna', name: 'Анна', avatar: 'url_to_image', relationType: 'family', connectionStrength: 0.92, hasOwnConnections: false },
],
};
// Связанный мульти-пользовательский граф для лаборатории (network-view/lab):
// у каждого пользователя свой набор связей, тап по узлу переключает карту на его сеть.
// Сияющими считаем ivan/alisa/oleg — у них статус подсвечивается и в их карточках у других.
const NETWORK_NAMES = {
ivan: 'Иван', alisa: 'Алиса', pavel: 'Павел', elena: 'Елена', dmitry: 'Дмитрий',
oleg: 'Олег', nina: 'Нина', marina: 'Марина', sveta: 'Света', kirill: 'Кирилл',
};
const NETWORK_SHINING = new Set(['ivan', 'alisa', 'oleg', 'marina', 'nina']);
// Тестовые аватарки-фото (реальные лица по сид-номеру pravatar) — только для лаборатории.
// Если сети нет — узлы мягко падают на инициалы (img.onerror).
const NETWORK_PHOTOS = {
ivan: 'https://i.pravatar.cc/150?img=12', alisa: 'https://i.pravatar.cc/150?img=5',
pavel: 'https://i.pravatar.cc/150?img=13', elena: 'https://i.pravatar.cc/150?img=9',
dmitry: 'https://i.pravatar.cc/150?img=33', oleg: 'https://i.pravatar.cc/150?img=52',
nina: 'https://i.pravatar.cc/150?img=47', marina: 'https://i.pravatar.cc/150?img=44',
sveta: 'https://i.pravatar.cc/150?img=24', kirill: 'https://i.pravatar.cc/150?img=60',
};
function networkConn(login, relationType, connectionStrength) {
return {
id: login,
login,
name: NETWORK_NAMES[login] || login,
avatar: null,
photo: NETWORK_PHOTOS[login] || null,
relationType,
connectionStrength,
hasOwnConnections: true,
status: NETWORK_SHINING.has(login) ? 'shining' : '',
};
}
function networkPerson(login, connections) {
return {
focusUser: {
id: login,
login,
name: NETWORK_NAMES[login] || login,
avatar: null,
photo: NETWORK_PHOTOS[login] || null,
status: NETWORK_SHINING.has(login) ? 'shining' : '',
},
connections,
};
}
export const networkGraphUsers = {
ivan: networkPerson('ivan', [
networkConn('alisa', 'friend', 0.9),
networkConn('pavel', 'friend', 0.7),
networkConn('elena', 'family', 0.95),
networkConn('dmitry', 'family', 0.95),
networkConn('oleg', 'business', 0.5),
networkConn('nina', 'contact', 0.35),
networkConn('kirill', 'friend', 0.6),
]),
alisa: networkPerson('alisa', [
networkConn('ivan', 'friend', 0.9),
networkConn('marina', 'friend', 0.8),
networkConn('sveta', 'contact', 0.4),
networkConn('elena', 'contact', 0.3),
]),
pavel: networkPerson('pavel', [
networkConn('ivan', 'friend', 0.7),
networkConn('oleg', 'business', 0.6),
networkConn('kirill', 'friend', 0.5),
]),
elena: networkPerson('elena', [
networkConn('ivan', 'family', 0.95),
networkConn('dmitry', 'family', 0.9),
networkConn('alisa', 'contact', 0.3),
]),
dmitry: networkPerson('dmitry', [
networkConn('ivan', 'family', 0.95),
networkConn('elena', 'family', 0.9),
networkConn('pavel', 'business', 0.4),
]),
oleg: networkPerson('oleg', [
networkConn('pavel', 'business', 0.6),
networkConn('ivan', 'business', 0.5),
networkConn('nina', 'contact', 0.45),
]),
nina: networkPerson('nina', [
networkConn('ivan', 'contact', 0.35),
networkConn('oleg', 'contact', 0.45),
networkConn('sveta', 'friend', 0.5),
]),
marina: networkPerson('marina', [
networkConn('alisa', 'friend', 0.8),
networkConn('sveta', 'friend', 0.7),
networkConn('kirill', 'contact', 0.4),
]),
sveta: networkPerson('sveta', [
networkConn('marina', 'friend', 0.7),
networkConn('alisa', 'contact', 0.4),
networkConn('nina', 'friend', 0.5),
]),
kirill: networkPerson('kirill', [
networkConn('ivan', 'friend', 0.6),
networkConn('pavel', 'friend', 0.5),
networkConn('marina', 'contact', 0.4),
]),
};