feat(tradein/ui): admin links to audit + analytics in UserMenu (#2524)
All checks were successful
Deploy Trade-In / build-frontend (push) Successful in 1m54s
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 55s
All checks were successful
Deploy Trade-In / build-frontend (push) Successful in 1m54s
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 55s
Admin-only «Аудит доступа» → /admin/audit and «Активность» → /admin/analytics links in the UserMenu dropdown. Navigates via API_BASE_URL prefix (Topbar convention, basePath-safe). Pilot menu unchanged.
This commit is contained in:
parent
c61ed5a96e
commit
67b50bf713
1 changed files with 94 additions and 0 deletions
|
|
@ -19,8 +19,10 @@
|
||||||
* покажется заново.
|
* покажется заново.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { CSSProperties } from "react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
import { API_BASE_URL } from "@/lib/api";
|
||||||
import { logout } from "@/lib/logout";
|
import { logout } from "@/lib/logout";
|
||||||
|
|
||||||
import { useMe } from "@/lib/useMe";
|
import { useMe } from "@/lib/useMe";
|
||||||
|
|
@ -46,6 +48,69 @@ function LogOutIcon() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Inline Shield icon (lucide-react `Shield` SVG path, stroke 1.5) — для
|
||||||
|
admin-ссылки «Аудит доступа». Та же inline-SVG конвенция, что LogOutIcon
|
||||||
|
(tradein-mvp не тянет lucide-react в deps). */
|
||||||
|
function ShieldIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={16}
|
||||||
|
height={16}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Inline BarChart icon (lucide-react `BarChart3` SVG path, stroke 1.5) —
|
||||||
|
для admin-ссылки «Активность». */
|
||||||
|
function BarChartIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={16}
|
||||||
|
height={16}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d="M3 3v16a2 2 0 0 0 2 2h16" />
|
||||||
|
<path d="M18 17V9" />
|
||||||
|
<path d="M13 17V5" />
|
||||||
|
<path d="M8 17v-3" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Общий inline-стиль для admin-nav-пунктов дропдауна (Аудит/Активность) —
|
||||||
|
тот же паттерн, что «Выйти», но нейтральный цвет вместо var(--danger). */
|
||||||
|
const adminMenuItemStyle: CSSProperties = {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 8,
|
||||||
|
width: "100%",
|
||||||
|
background: "none",
|
||||||
|
border: "none",
|
||||||
|
padding: "4px 0",
|
||||||
|
cursor: "pointer",
|
||||||
|
color: "var(--fg-primary)",
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: 14,
|
||||||
|
textAlign: "left",
|
||||||
|
fontFamily: "inherit",
|
||||||
|
textDecoration: "none",
|
||||||
|
};
|
||||||
|
|
||||||
export function UserMenu() {
|
export function UserMenu() {
|
||||||
const { data, isLoading, error } = useMe();
|
const { data, isLoading, error } = useMe();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
@ -159,6 +224,35 @@ export function UserMenu() {
|
||||||
>
|
>
|
||||||
{roleLabel}
|
{roleLabel}
|
||||||
</div>
|
</div>
|
||||||
|
{data.role === "admin" && (
|
||||||
|
<>
|
||||||
|
<hr
|
||||||
|
style={{
|
||||||
|
margin: "12px 0",
|
||||||
|
border: "none",
|
||||||
|
borderTop: "1px solid var(--border-soft)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
role="menuitem"
|
||||||
|
href={`${API_BASE_URL}/admin/audit`}
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
style={adminMenuItemStyle}
|
||||||
|
>
|
||||||
|
<ShieldIcon />
|
||||||
|
Аудит доступа
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
role="menuitem"
|
||||||
|
href={`${API_BASE_URL}/admin/analytics`}
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
style={{ ...adminMenuItemStyle, marginTop: 4 }}
|
||||||
|
>
|
||||||
|
<BarChartIcon />
|
||||||
|
Активность
|
||||||
|
</a>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<hr
|
<hr
|
||||||
style={{
|
style={{
|
||||||
margin: "12px 0",
|
margin: "12px 0",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue