diff --git a/frontend/src/pages/DigestPage.tsx b/frontend/src/pages/DigestPage.tsx index 332c3fe..838b2e7 100644 --- a/frontend/src/pages/DigestPage.tsx +++ b/frontend/src/pages/DigestPage.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; -import { Radio, Button, message, Tooltip, theme } from 'antd'; +import { Radio, Button, message, Tooltip, theme, Row, Col } from 'antd'; import { ReloadOutlined } from '@ant-design/icons'; import { useWorkspaceStore } from '../store/workspace.store'; import { useDigest } from '../hooks/useDigest'; @@ -44,7 +44,7 @@ export default function DigestPage() { const navigate = useNavigate(); const { token } = theme.useToken(); const { workspaces, current, setCurrent, load } = useWorkspaceStore(); - const [scope, setScope] = useState('personal'); + const [scope, setScope] = useState(null); const [period, setPeriod] = useState('7d'); const [statusMessage, setStatusMessage] = useState(''); @@ -64,19 +64,24 @@ export default function DigestPage() { const role = foundWs?.role; const isViewer = role === 'VIEWER'; + // Default scope: team for managers (Owner/Member), personal for viewers. + // Until user manually picks, follow the role-derived default. + const defaultScope: DigestScope = isViewer ? 'personal' : 'team'; + const activeScope: DigestScope = scope ?? defaultScope; + // Derive effective scope synchronously (no useEffect-loop): viewer is always personal. - const effectiveScope: DigestScope = isViewer && scope === 'team' ? 'personal' : scope; + const effectiveScope: DigestScope = isViewer && activeScope === 'team' ? 'personal' : activeScope; const { data, loading, error, forbiddenTeam, refetch } = useDigest(workspaceId, effectiveScope, period); // Auto-switch + toast when backend returns 403 (e.g. stale role on client). useEffect(() => { - if (forbiddenTeam && scope === 'team') { + if (forbiddenTeam && activeScope === 'team') { message.warning('Командный разрез недоступен (нужна роль Owner или Member). Показываем личные метрики.'); // eslint-disable-next-line react-hooks/set-state-in-effect setScope('personal'); } - }, [forbiddenTeam, scope]); + }, [forbiddenTeam, activeScope]); // Announce data refresh for screen readers via a dedicated live region. useEffect(() => { @@ -132,7 +137,7 @@ export default function DigestPage() {

Дайджест

handleScopeChange(e.target.value as DigestScope)} aria-label="Чьи задачи показывать" size="large" @@ -227,19 +232,14 @@ export default function DigestPage() { )} -
+ + @@ -279,13 +279,14 @@ export default function DigestPage() {
)} - + + {data && ( @@ -312,13 +313,14 @@ export default function DigestPage() { )} - + + @@ -357,13 +359,14 @@ export default function DigestPage() { )} - + + @@ -385,7 +388,8 @@ export default function DigestPage() { )} - + + ); }