Files
auth-portal/apps/web/src/design-preview/preview-store.ts
T
DenozordecandClaude Sonnet 5.5 007ece4575 feat(design-preview): страница пользователя с рейкой вкладок (solution-users-2)
Права, вход и passkeys, сессии, активность и опасная зона. Каталог пользователей вынесен в общее
состояние макета, поэтому правки видны и в списке, и в профиле. Переходы: меню строки «Профиль»,
«Открыть профиль» в панели прав, хлебные крошки в шапке.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-18 02:35:57 +07:00

54 lines
2.1 KiB
TypeScript

import { createContext, useContext, type Dispatch, type SetStateAction } from 'react'
import type { AdminUser } from '@authportal/shared'
export type ChangeKind = 'add' | 'chg' | 'del'
export type RowMark = 'new' | 'dirty' | 'deleted'
export type PendingChange = {
id: string
kind: ChangeKind
title: string
/** Раздел, к которому относятся пометки строк («users», «app-links»). */
resource?: string
/** Пометки строк: «Не сохранено» (dirty/new) и «Будет удалено» (deleted). */
marks?: Record<string, RowMark>
/** Выполняется при «Сохранить»: окончательно применяет правку (например, убирает удалённую строку). */
commit?: () => void
/** Строки diff: «+ …», «− …», « … ». */
lines: string[]
/** Откатывает локальное состояние страницы при «Отменить». */
revert?: () => void
}
export type Density = 'comfortable' | 'compact'
export type Contrast = 'standard' | 'high'
export type PreviewStore = {
pending: PendingChange[]
/** Пометки строк раздела из накопленных правок. */
marksFor: (resource: string) => Record<string, RowMark>
addChange: (change: Omit<PendingChange, 'id'>) => void
discardAll: () => void
applyAll: () => void
paletteOpen: boolean
setPaletteOpen: (open: boolean) => void
/** Каталог пользователей: общий для списка и профиля. */
users: AdminUser[]
setUsers: Dispatch<SetStateAction<AdminUser[]>>
pins: string[]
togglePin: (id: string) => void
density: Density
setDensity: (v: Density) => void
contrast: Contrast
setContrast: (v: Contrast) => void
}
export const PreviewStoreContext = createContext<PreviewStore | null>(null)
export function usePreviewStore(): PreviewStore {
const ctx = useContext(PreviewStoreContext)
if (!ctx) throw new Error('PreviewProvider отсутствует')
return ctx
}