fix(design-preview): убрать страницу пользователя — дублировала панель прав
Права, сброс passkeys, отключение и удаление уже есть в панели прав и меню строки,
сессии и события — в «Входах» и «Изменениях». Страница откроется из коммита 007ece4.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
1 parent
c8351424f4
commit
8bbaab62e4
7 files changed
+4
-373
No files matched your search
@@ -1,5 +1,4 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
import { ArrowUpRightIcon } from 'lucide-react'
|
||||
import type { AdminUser } from '@authportal/shared'
|
||||
import { Button } from '@authportal/ui/components/button'
|
||||
import { AccessEditor } from './access-editor'
|
||||
@@ -11,12 +10,10 @@ export function AccessSheet({
|
||||
user,
|
||||
onClose,
|
||||
onSave,
|
||||
onOpenProfile,
|
||||
}: {
|
||||
user: AdminUser
|
||||
onClose: () => void
|
||||
onSave: (value: AccessValue) => void
|
||||
onOpenProfile?: () => void
|
||||
}) {
|
||||
const [value, setValue] = useState<AccessValue>({ apps: user.apps, permissions: user.permissions })
|
||||
const changes = useMemo(() => diffAccess({ apps: user.apps, permissions: user.permissions }, value).length, [user, value])
|
||||
@@ -31,12 +28,6 @@ export function AccessSheet({
|
||||
description="Доступ к приложениям и разделам · иерархия: админ ⊃ запись ⊃ чтение"
|
||||
footer={
|
||||
<>
|
||||
{onOpenProfile ? (
|
||||
<Button variant="ghost" onClick={onOpenProfile}>
|
||||
Открыть профиль
|
||||
<ArrowUpRightIcon aria-hidden />
|
||||
</Button>
|
||||
) : null}
|
||||
<span className="text-muted-foreground mr-auto self-center text-xs">
|
||||
{changes > 0 ? `Изменений: ${changes}` : 'Без изменений'}
|
||||
</span>
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
import { Link, useNavigate, useParams } from '@tanstack/react-router'
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
FingerprintIcon,
|
||||
HistoryIcon,
|
||||
MonitorSmartphoneIcon,
|
||||
ShieldCheckIcon,
|
||||
TriangleAlertIcon,
|
||||
} from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import type { AdminUser } from '@authportal/shared'
|
||||
import { AuditLogTimeline } from '@/components/reui-kit/audit-log-timeline'
|
||||
import { Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle } from '@/components/reui/frame'
|
||||
import { Avatar, AvatarFallback } from '@authportal/ui/components/avatar'
|
||||
import { Button } from '@authportal/ui/components/button'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@authportal/ui/components/tabs'
|
||||
import { AccessEditor } from '../access-editor'
|
||||
import { diffAccess, type AccessValue } from '../access-model'
|
||||
import { KvFrame, PendingChip, StatusBadge, TypedConfirm } from '../bits'
|
||||
import { MOCK_AUDIT, MOCK_SESSIONS, USER_META, type SessionRow } from '../mock'
|
||||
import { usePreviewStore } from '../preview-store'
|
||||
import { PreviewSectionGrid, TwoLineCell, type GridColumn } from '../section-grid'
|
||||
import { usePatchUsers } from '../user-actions'
|
||||
|
||||
function initials(u: AdminUser) {
|
||||
const base = (u.name || u.email).trim()
|
||||
const parts = base.split(/\s+/)
|
||||
return (parts.length > 1 ? `${parts[0]![0]}${parts[1]![0]}` : base.slice(0, 2)).toUpperCase()
|
||||
}
|
||||
|
||||
function statusOf(u: AdminUser) {
|
||||
if (u.disabled) return { tone: 'mu' as const, label: 'Отключён' }
|
||||
if (u.passkey_count === 0) return { tone: 'wn' as const, label: 'Без passkey' }
|
||||
return { tone: 'ok' as const, label: 'Активен' }
|
||||
}
|
||||
|
||||
/** Страница пользователя (solution-users-2): рейка вкладок — права, вход, сессии, активность, опасная зона. */
|
||||
export function UserProfilePage() {
|
||||
const { userId } = useParams({ from: '/design-preview/_shell/users/$userId' })
|
||||
const { users, setUsers, addChange, marksFor } = usePreviewStore()
|
||||
const navigate = useNavigate()
|
||||
const patch = usePatchUsers()
|
||||
const user = users.find((u) => u.id === userId)
|
||||
const mark = marksFor('users')[userId]
|
||||
|
||||
const [draft, setDraft] = useState<{ id: string; value: AccessValue } | null>(null)
|
||||
const [sessions, setSessions] = useState<SessionRow[]>(MOCK_SESSIONS)
|
||||
const [resetOpen, setResetOpen] = useState(false)
|
||||
const [deleteOpen, setDeleteOpen] = useState(false)
|
||||
|
||||
const sessionRows = useMemo(() => sessions.filter((s) => s.user === user?.email), [sessions, user])
|
||||
const events = useMemo(
|
||||
() => MOCK_AUDIT.filter((e) => e.actor_email === user?.email || e.summary.includes(user?.email ?? '\0')),
|
||||
[user],
|
||||
)
|
||||
|
||||
if (!user) {
|
||||
return (
|
||||
<Frame spacing="sm" className="w-full">
|
||||
<FramePanel className="flex flex-col items-start gap-3 py-8">
|
||||
<p className="font-medium">Пользователь не найден</p>
|
||||
<p className="text-muted-foreground text-sm">Возможно, учётная запись уже удалена.</p>
|
||||
<Button variant="outline" render={<Link to="/design-preview/users" />} nativeButton={false}>
|
||||
<ArrowLeftIcon aria-hidden />К списку пользователей
|
||||
</Button>
|
||||
</FramePanel>
|
||||
</Frame>
|
||||
)
|
||||
}
|
||||
|
||||
const status = statusOf(user)
|
||||
const base: AccessValue = { apps: user.apps, permissions: user.permissions }
|
||||
const value = draft?.id === user.id ? draft.value : base
|
||||
const changes = diffAccess(base, value).length
|
||||
|
||||
const sessionColumns: GridColumn<SessionRow>[] = [
|
||||
{ id: 'ip', title: 'IP · клиент', size: 260, cell: (r) => <TwoLineCell dot={r.tone} title={r.ipClient} sub={r.note || undefined} /> },
|
||||
{ id: 'created', title: 'Создана', size: 140, cell: (r) => <span className="text-sm whitespace-nowrap">{r.created}</span> },
|
||||
{ id: 'exp', title: 'Истекает', size: 120, cell: (r) => <span className="text-sm whitespace-nowrap">{r.expires}</span> },
|
||||
{
|
||||
id: 'act',
|
||||
title: '',
|
||||
size: 130,
|
||||
cell: (r) => (
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setSessions((s) => s.filter((x) => x.id !== r.id))
|
||||
toast.success('Сессия завершена (макет)')
|
||||
}}
|
||||
>
|
||||
Завершить
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<>
|
||||
<Frame spacing="sm" className="w-full">
|
||||
<FramePanel className="flex flex-wrap items-center gap-x-4 gap-y-3">
|
||||
<Avatar className="size-12 rounded-xl">
|
||||
<AvatarFallback className="rounded-xl text-sm">{initials(user)}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex min-w-0 flex-1 basis-60 flex-col gap-1">
|
||||
<h1 className="truncate text-xl font-semibold tracking-tight">{user.email}</h1>
|
||||
<p className="text-muted-foreground truncate font-mono text-[11px]">{USER_META[user.id]?.sub ?? user.name}</p>
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
<StatusBadge tone={status.tone}>{status.label}</StatusBadge>
|
||||
<StatusBadge tone={user.is_admin ? 'wn' : 'in'}>{user.is_admin ? 'Админ' : 'Пользователь'}</StatusBadge>
|
||||
{mark ? <PendingChip mark={mark} /> : null}
|
||||
</div>
|
||||
</div>
|
||||
<Button variant="outline" render={<Link to="/design-preview/users" />} nativeButton={false}>
|
||||
<ArrowLeftIcon aria-hidden />К списку
|
||||
</Button>
|
||||
</FramePanel>
|
||||
</Frame>
|
||||
|
||||
<Tabs defaultValue="access" className="min-w-0 flex-col gap-4 md:flex-row md:items-start">
|
||||
<TabsList className="h-auto! w-full flex-row flex-wrap justify-start md:w-56 md:shrink-0 md:flex-col md:items-stretch">
|
||||
<TabsTrigger value="access" className="justify-start">
|
||||
<ShieldCheckIcon aria-hidden />
|
||||
Права доступа
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="auth" className="justify-start">
|
||||
<FingerprintIcon aria-hidden />
|
||||
Вход и passkeys
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="sessions" className="justify-start">
|
||||
<MonitorSmartphoneIcon aria-hidden />
|
||||
Сессии · {sessionRows.length}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="activity" className="justify-start">
|
||||
<HistoryIcon aria-hidden />
|
||||
Активность
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="danger" className="justify-start">
|
||||
<TriangleAlertIcon aria-hidden />
|
||||
Опасная зона
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<div className="min-w-0 flex-1">
|
||||
<TabsContent value="access" className="min-w-0">
|
||||
<Frame spacing="sm" className="w-full">
|
||||
<FrameHeader>
|
||||
<FrameTitle>Права доступа</FrameTitle>
|
||||
<FrameDescription>Приложения и разделы · иерархия: админ ⊃ запись ⊃ чтение</FrameDescription>
|
||||
</FrameHeader>
|
||||
<FramePanel>
|
||||
<AccessEditor user={user} value={value} onChange={(next) => setDraft({ id: user.id, value: next })} />
|
||||
</FramePanel>
|
||||
<FrameFooter className="flex-wrap justify-end gap-2">
|
||||
<span className="text-muted-foreground mr-auto text-xs">{changes > 0 ? `Изменений: ${changes}` : 'Без изменений'}</span>
|
||||
<Button variant="outline" disabled={changes === 0} onClick={() => setDraft(null)}>
|
||||
Сбросить
|
||||
</Button>
|
||||
<Button
|
||||
disabled={changes === 0}
|
||||
onClick={() => {
|
||||
patch(
|
||||
[user.id],
|
||||
(u) => ({ ...u, apps: value.apps, permissions: value.permissions }),
|
||||
`Права обновлены: ${user.email}`,
|
||||
() => diffAccess(base, value),
|
||||
)
|
||||
setDraft(null)
|
||||
}}
|
||||
>
|
||||
Сохранить права
|
||||
</Button>
|
||||
</FrameFooter>
|
||||
</Frame>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="auth" className="flex min-w-0 flex-col gap-4">
|
||||
<KvFrame
|
||||
title="Вход"
|
||||
description="Способы входа учётной записи"
|
||||
items={[
|
||||
{ label: 'Пароль', value: 'Задан · запасной вход' },
|
||||
{ label: 'Passkeys', value: user.passkey_count === 0 ? 'нет' : `${user.passkey_count} шт.` },
|
||||
{ label: 'Последний вход', value: USER_META[user.id]?.activity ?? '—' },
|
||||
{ label: 'Статус', value: status.label },
|
||||
]}
|
||||
/>
|
||||
<Frame spacing="sm" className="w-full">
|
||||
<FramePanel className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div className="flex min-w-0 flex-col">
|
||||
<span className="text-sm font-medium">Сбросить passkeys…</span>
|
||||
<span className="text-muted-foreground text-xs">Войти можно будет только по паролю, пока не добавлен новый ключ.</span>
|
||||
</div>
|
||||
<Button variant="outline" disabled={user.passkey_count === 0} onClick={() => setResetOpen(true)}>
|
||||
Сбросить
|
||||
</Button>
|
||||
</FramePanel>
|
||||
</Frame>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="sessions" className="min-w-0">
|
||||
<PreviewSectionGrid
|
||||
title="Активные сессии"
|
||||
description="Завершение сессии выкидывает пользователя из портала и приложений"
|
||||
rows={sessionRows}
|
||||
columns={sessionColumns}
|
||||
getRowId={(r) => r.id}
|
||||
emptyMessage="Нет активных сессий."
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="activity" className="min-w-0">
|
||||
<Frame spacing="sm" className="w-full">
|
||||
<FrameHeader>
|
||||
<FrameTitle>Активность</FrameTitle>
|
||||
<FrameDescription>События пользователя из журнала портала</FrameDescription>
|
||||
</FrameHeader>
|
||||
<FramePanel>
|
||||
{events.length === 0 ? (
|
||||
<p className="text-muted-foreground text-sm">Событий нет.</p>
|
||||
) : (
|
||||
<AuditLogTimeline entries={events} totalCount={events.length} compact lockedUserId={user.id} />
|
||||
)}
|
||||
</FramePanel>
|
||||
</Frame>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="danger" className="min-w-0">
|
||||
<Frame spacing="sm" className="w-full">
|
||||
<FrameHeader>
|
||||
<FrameTitle>Опасная зона</FrameTitle>
|
||||
<FrameDescription>Действия попадают в «Не сохранено» и в журнал</FrameDescription>
|
||||
</FrameHeader>
|
||||
<FramePanel className="p-0">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3 border-b px-4 py-3">
|
||||
<div className="flex min-w-0 flex-col">
|
||||
<span className="text-sm font-medium">{user.disabled ? 'Включить учётную запись' : 'Отключить учётную запись'}</span>
|
||||
<span className="text-muted-foreground text-xs">Вход закрывается, учётная запись и права сохраняются.</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
patch([user.id], (u) => ({ ...u, disabled: !u.disabled }), `${user.disabled ? 'Включён' : 'Отключён'} ${user.email}`, (b, a) => [
|
||||
`− disabled: ${String(b.disabled)}`,
|
||||
`+ disabled: ${String(a.disabled)}`,
|
||||
])
|
||||
}
|
||||
>
|
||||
{user.disabled ? 'Включить' : 'Отключить'}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center justify-between gap-3 px-4 py-3">
|
||||
<div className="flex min-w-0 flex-col">
|
||||
<span className="text-sm font-medium">Удалить пользователя…</span>
|
||||
<span className="text-muted-foreground text-xs">Учётная запись и все права будут удалены безвозвратно.</span>
|
||||
</div>
|
||||
<Button variant="destructive" onClick={() => setDeleteOpen(true)}>
|
||||
Удалить…
|
||||
</Button>
|
||||
</div>
|
||||
</FramePanel>
|
||||
</Frame>
|
||||
</TabsContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
|
||||
<TypedConfirm
|
||||
open={resetOpen}
|
||||
onOpenChange={setResetOpen}
|
||||
title="Сбросить passkeys пользователя?"
|
||||
description={`Все ключи ${user.email} будут удалены. Войти можно будет только по паролю. Действие попадёт в журнал.`}
|
||||
expected="сбросить"
|
||||
confirmLabel="Сбросить"
|
||||
onConfirm={() => {
|
||||
patch([user.id], (u) => ({ ...u, passkey_count: 0 }), `Сброс passkeys: ${user.email}`, (b) => [`− passkeys: ${b.passkey_count}`, '+ passkeys: 0'])
|
||||
setResetOpen(false)
|
||||
}}
|
||||
/>
|
||||
<TypedConfirm
|
||||
open={deleteOpen}
|
||||
onOpenChange={setDeleteOpen}
|
||||
title="Удалить пользователя?"
|
||||
description={`Учётная запись ${user.email} и её права будут удалены. Действие попадёт в панель «Не сохранено» и в журнал.`}
|
||||
expected={user.email}
|
||||
confirmLabel="Удалить"
|
||||
onConfirm={() => {
|
||||
addChange({
|
||||
kind: 'del',
|
||||
title: `Удалён ${user.email}`,
|
||||
lines: [`− email: ${user.email}`, `− apps: ${user.apps.length}`],
|
||||
resource: 'users',
|
||||
marks: { [user.id]: 'deleted' },
|
||||
commit: () => setUsers((prev) => prev.filter((u) => u.id !== user.id)),
|
||||
})
|
||||
setDeleteOpen(false)
|
||||
void navigate({ to: '/design-preview/users' })
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { UsersIcon, ShieldCheckIcon, FingerprintIcon, UserXIcon } from 'lucide-react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useNavigate } from '@tanstack/react-router'
|
||||
import { toast } from 'sonner'
|
||||
import type { AdminUser, CreateUserRequest } from '@authportal/shared'
|
||||
import { CreateUserSheet } from '@/components/reui-kit/create-user-sheet'
|
||||
@@ -26,7 +25,6 @@ export function UsersPage() {
|
||||
usersRef.current = users
|
||||
}, [users])
|
||||
const patch = usePatchUsers()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const [createOpen, setCreateOpen] = useState(false)
|
||||
const [journalFor, setJournalFor] = useState<AdminUser | null>(null)
|
||||
@@ -86,7 +84,6 @@ export function UsersPage() {
|
||||
onToggleDisabled: onDeactivate,
|
||||
onResetPasskeys,
|
||||
onDelete,
|
||||
onOpenProfile: (u) => void navigate({ to: '/design-preview/users/$userId', params: { userId: u.id } }),
|
||||
onBulkDelete: (ids) => setBulkDeleteIds(ids),
|
||||
onBulkDisabled: (ids, disabled) =>
|
||||
patch(ids, (u) => ({ ...u, disabled }), `${disabled ? 'Отключено' : 'Включено'} пользователей: ${ids.length}`, () => [
|
||||
@@ -151,9 +148,6 @@ export function UsersPage() {
|
||||
key={accessFor.id}
|
||||
user={accessFor}
|
||||
onClose={() => setAccessFor(null)}
|
||||
onOpenProfile={() => {
|
||||
void navigate({ to: '/design-preview/users/$userId', params: { userId: accessFor.id } })
|
||||
}}
|
||||
onSave={(value: AccessValue) => {
|
||||
const target = accessFor
|
||||
patch(
|
||||
|
||||
@@ -31,10 +31,8 @@ import { Avatar, AvatarFallback } from '@authportal/ui/components/avatar'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@authportal/ui/components/breadcrumb'
|
||||
import { Button } from '@authportal/ui/components/button'
|
||||
import {
|
||||
@@ -474,9 +472,7 @@ function FreshnessPopover() {
|
||||
|
||||
export function PreviewHeader() {
|
||||
const pathname = useRouterState({ select: (s) => s.location.pathname })
|
||||
const { setPaletteOpen, users } = usePreviewStore()
|
||||
const profileId = /^\/design-preview\/users\/([^/]+)/.exec(pathname)?.[1]
|
||||
const profileUser = profileId ? users.find((u) => u.id === profileId) : undefined
|
||||
const { setPaletteOpen } = usePreviewStore()
|
||||
const current = NAV_ITEMS.find((i) => pathname === i.to || pathname.startsWith(`${i.to}/`))
|
||||
|
||||
return (
|
||||
@@ -485,21 +481,9 @@ export function PreviewHeader() {
|
||||
<Separator orientation="vertical" className="mr-2 data-[orientation=vertical]:h-4" />
|
||||
<Breadcrumb className="min-w-0">
|
||||
<BreadcrumbList className="flex-nowrap">
|
||||
{profileUser ? (
|
||||
<>
|
||||
<BreadcrumbItem className="hidden @md/header:inline-flex">
|
||||
<BreadcrumbLink render={<Link to="/design-preview/users" />}>Пользователи</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className="hidden @md/header:block" />
|
||||
<BreadcrumbItem className="min-w-0">
|
||||
<BreadcrumbPage className="truncate">{profileUser.email}</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</>
|
||||
) : (
|
||||
<BreadcrumbItem className="min-w-0">
|
||||
<BreadcrumbPage className="truncate">{current?.label ?? 'Макет'}</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
)}
|
||||
<BreadcrumbItem className="min-w-0">
|
||||
<BreadcrumbPage className="truncate">{current?.label ?? 'Макет'}</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<div className="ml-auto flex shrink-0 items-center gap-2">
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
ScrollTextIcon,
|
||||
ShieldCheckIcon,
|
||||
Trash2Icon,
|
||||
UserRoundIcon,
|
||||
FingerprintIcon,
|
||||
} from 'lucide-react'
|
||||
import type { AdminUser } from '@authportal/shared'
|
||||
@@ -43,7 +42,6 @@ function passkeyLabel(n: number) {
|
||||
|
||||
export type UsersGridHandlers = {
|
||||
onOpenAccess: (u: AdminUser) => void
|
||||
onOpenProfile: (u: AdminUser) => void
|
||||
onOpenJournal: (u: AdminUser) => void
|
||||
onToggleDisabled: (u: AdminUser) => void
|
||||
onResetPasskeys: (u: AdminUser) => void
|
||||
@@ -91,10 +89,6 @@ export function UsersGrid({ users, handlers, marks }: { users: AdminUser[]; hand
|
||||
<ShieldCheckIcon aria-hidden />
|
||||
Права доступа
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handlers.onOpenProfile(u)}>
|
||||
<UserRoundIcon aria-hidden />
|
||||
Профиль
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handlers.onOpenJournal(u)}>
|
||||
<ScrollTextIcon aria-hidden />
|
||||
Журнал
|
||||
|
||||
@@ -32,7 +32,6 @@ import { Route as DesignPreviewShellLoginsRouteImport } from './routes/design-pr
|
||||
import { Route as DesignPreviewShellOidcRouteImport } from './routes/design-preview._shell.oidc'
|
||||
import { Route as AuthAdminUsersUserIdRouteImport } from './routes/_auth.admin.users.$userId'
|
||||
import { Route as DesignPreviewShellUsersIndexRouteImport } from './routes/design-preview._shell.users.index'
|
||||
import { Route as DesignPreviewShellUsersUserIdRouteImport } from './routes/design-preview._shell.users.$userId'
|
||||
|
||||
const IndexRoute = IndexRouteImport.update({
|
||||
id: '/',
|
||||
@@ -151,12 +150,6 @@ const DesignPreviewShellUsersIndexRoute =
|
||||
path: '/users/',
|
||||
getParentRoute: () => DesignPreviewShellRoute,
|
||||
} as any)
|
||||
const DesignPreviewShellUsersUserIdRoute =
|
||||
DesignPreviewShellUsersUserIdRouteImport.update({
|
||||
id: '/users/$userId',
|
||||
path: '/users/$userId',
|
||||
getParentRoute: () => DesignPreviewShellRoute,
|
||||
} as any)
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
@@ -179,7 +172,6 @@ export interface FileRoutesByFullPath {
|
||||
'/design-preview/oidc': typeof DesignPreviewShellOidcRoute
|
||||
'/admin/': typeof AuthAdminIndexRoute
|
||||
'/admin/users/$userId': typeof AuthAdminUsersUserIdRoute
|
||||
'/design-preview/users/$userId': typeof DesignPreviewShellUsersUserIdRoute
|
||||
'/design-preview/users/': typeof DesignPreviewShellUsersIndexRoute
|
||||
}
|
||||
export interface FileRoutesByTo {
|
||||
@@ -201,7 +193,6 @@ export interface FileRoutesByTo {
|
||||
'/design-preview/oidc': typeof DesignPreviewShellOidcRoute
|
||||
'/admin': typeof AuthAdminIndexRoute
|
||||
'/admin/users/$userId': typeof AuthAdminUsersUserIdRoute
|
||||
'/design-preview/users/$userId': typeof DesignPreviewShellUsersUserIdRoute
|
||||
'/design-preview/users': typeof DesignPreviewShellUsersIndexRoute
|
||||
}
|
||||
export interface FileRoutesById {
|
||||
@@ -228,7 +219,6 @@ export interface FileRoutesById {
|
||||
'/design-preview/_shell/oidc': typeof DesignPreviewShellOidcRoute
|
||||
'/_auth/admin/': typeof AuthAdminIndexRoute
|
||||
'/_auth/admin/users/$userId': typeof AuthAdminUsersUserIdRoute
|
||||
'/design-preview/_shell/users/$userId': typeof DesignPreviewShellUsersUserIdRoute
|
||||
'/design-preview/_shell/users/': typeof DesignPreviewShellUsersIndexRoute
|
||||
}
|
||||
export interface FileRouteTypes {
|
||||
@@ -254,7 +244,6 @@ export interface FileRouteTypes {
|
||||
| '/design-preview/oidc'
|
||||
| '/admin/'
|
||||
| '/admin/users/$userId'
|
||||
| '/design-preview/users/$userId'
|
||||
| '/design-preview/users/'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
@@ -276,7 +265,6 @@ export interface FileRouteTypes {
|
||||
| '/design-preview/oidc'
|
||||
| '/admin'
|
||||
| '/admin/users/$userId'
|
||||
| '/design-preview/users/$userId'
|
||||
| '/design-preview/users'
|
||||
id:
|
||||
| '__root__'
|
||||
@@ -302,7 +290,6 @@ export interface FileRouteTypes {
|
||||
| '/design-preview/_shell/oidc'
|
||||
| '/_auth/admin/'
|
||||
| '/_auth/admin/users/$userId'
|
||||
| '/design-preview/_shell/users/$userId'
|
||||
| '/design-preview/_shell/users/'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
@@ -476,13 +463,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof DesignPreviewShellUsersIndexRouteImport
|
||||
parentRoute: typeof DesignPreviewShellRoute
|
||||
}
|
||||
'/design-preview/_shell/users/$userId': {
|
||||
id: '/design-preview/_shell/users/$userId'
|
||||
path: '/users/$userId'
|
||||
fullPath: '/design-preview/users/$userId'
|
||||
preLoaderRoute: typeof DesignPreviewShellUsersUserIdRouteImport
|
||||
parentRoute: typeof DesignPreviewShellRoute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,7 +509,6 @@ interface DesignPreviewShellRouteChildren {
|
||||
DesignPreviewShellAuditRoute: typeof DesignPreviewShellAuditRoute
|
||||
DesignPreviewShellLoginsRoute: typeof DesignPreviewShellLoginsRoute
|
||||
DesignPreviewShellOidcRoute: typeof DesignPreviewShellOidcRoute
|
||||
DesignPreviewShellUsersUserIdRoute: typeof DesignPreviewShellUsersUserIdRoute
|
||||
DesignPreviewShellUsersIndexRoute: typeof DesignPreviewShellUsersIndexRoute
|
||||
}
|
||||
|
||||
@@ -540,7 +519,6 @@ const DesignPreviewShellRouteChildren: DesignPreviewShellRouteChildren = {
|
||||
DesignPreviewShellAuditRoute: DesignPreviewShellAuditRoute,
|
||||
DesignPreviewShellLoginsRoute: DesignPreviewShellLoginsRoute,
|
||||
DesignPreviewShellOidcRoute: DesignPreviewShellOidcRoute,
|
||||
DesignPreviewShellUsersUserIdRoute: DesignPreviewShellUsersUserIdRoute,
|
||||
DesignPreviewShellUsersIndexRoute: DesignPreviewShellUsersIndexRoute,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { UserProfilePage } from '@/design-preview/pages/user-profile-page'
|
||||
|
||||
export const Route = createFileRoute('/design-preview/_shell/users/$userId')({
|
||||
component: UserProfilePage,
|
||||
})
|
||||
Reference in new issue
Block a user