// SPDX-License-Identifier: AGPL-3.0-or-later // Admin shell (05 §2): sidebar in spec order; unbuilt pages say which milestone brings them. import { useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import { NavLink, Outlet, useNavigate } from 'react-router'; import { APP_NAME, type AuthUser } from '@selfphoneng/shared'; import { authApi } from '../../api/client.ts'; import { ThemeToggle } from '../../components/ThemeToggle.tsx'; import { Button } from '../../components/ui.tsx'; export const ADMIN_PAGES = [ { path: '', label: 'Dashboard', milestone: 'M2' }, { path: 'users', label: 'Users & Extensions', milestone: null }, { path: 'trunks', label: 'Trunks', milestone: 'M3' }, { path: 'numbers', label: 'Phone numbers', milestone: 'M3' }, { path: 'outbound', label: 'Outbound rules', milestone: 'M3' }, { path: 'ring-groups', label: 'Ring groups', milestone: 'M6' }, { path: 'queues', label: 'Queues', milestone: 'M8' }, { path: 'ivrs', label: 'Digital receptionist', milestone: 'M6' }, { path: 'hours', label: 'Office hours', milestone: 'M6' }, { path: 'conferences', label: 'Conferences', milestone: 'M8' }, { path: 'paging', label: 'Paging', milestone: 'M8' }, { path: 'sounds', label: 'Sounds & music', milestone: 'M6' }, { path: 'devices', label: 'Phones', milestone: 'M10' }, { path: 'contacts', label: 'Contacts', milestone: 'M10' }, { path: 'calls', label: 'Call history', milestone: 'M7' }, { path: 'recordings', label: 'Recordings', milestone: 'M7' }, { path: 'reports', label: 'Reports', milestone: 'M11' }, { path: 'sms', label: 'SMS', milestone: 'M9' }, { path: 'blocked', label: 'Blocked numbers', milestone: 'M6' }, { path: 'settings', label: 'Settings', milestone: 'M3' }, { path: 'system', label: 'System', milestone: 'M2' }, ] as const; export function AdminLayout({ user }: { user: AuthUser }) { const [navOpen, setNavOpen] = useState(false); const qc = useQueryClient(); const nav = useNavigate(); async function logout() { await authApi.logout().catch(() => undefined); qc.clear(); nav('/login', { replace: true }); } const links = ( ); return (
Coming in {milestone}.