Files
MikrotikManager/components/apps-menu.tsx
T
DenozordecandCursor 5f29cfaf0f
Docker images / prepare-release (push) Successful in 4s
Docker images / backend-image (push) Failing after 2m36s
Docker images / frontend-image (push) Successful in 2m22s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 55s
Docker images / publish-release (push) Skipped
fix(ui): выровнять chrome Frame и убрать Card-оболочки
Подключить App Switcher, NavUser, OpsPanel и AlertDialog вместо Card-shell.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 15:36:56 +07:00

97 lines
3.0 KiB
TypeScript

"use client"
import { LayoutGridIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
APP_SWITCHER_ICONS,
CURRENT_APP_ID,
authPortalBaseUrl,
} from "@/lib/app-switcher-config"
import { useAppSwitcherConfig } from "@/hooks/use-app-switcher"
/** Header apps grid — app-shell-12. @see https://reui.io/preview/base/app-shell-12 */
export function AppsMenu() {
const { config, isLoading } = useAppSwitcherConfig()
const portalBase = authPortalBaseUrl()
const portalAppsUrl = portalBase ? `${portalBase}/admin/apps` : null
return (
<DropdownMenu>
<DropdownMenuTrigger
render={
<Button variant="ghost" size="icon" aria-label="Приложения" />
}
>
<LayoutGridIcon className="size-4.5" aria-hidden="true" />
</DropdownMenuTrigger>
<DropdownMenuContent
side="bottom"
align="end"
sideOffset={8}
className="w-72"
>
<DropdownMenuGroup>
<DropdownMenuLabel>
{isLoading ? "Загрузка…" : config.menuLabel}
</DropdownMenuLabel>
<div className="grid grid-cols-3 gap-1 p-1">
{config.apps.map((app) => {
const Icon = APP_SWITCHER_ICONS[app.icon] ?? APP_SWITCHER_ICONS.server
const isCurrent = app.id === CURRENT_APP_ID
if (isCurrent) {
return (
<DropdownMenuItem
key={app.id}
disabled
className="h-auto flex-col gap-1.5 py-3 text-center [&_svg]:size-5"
>
<span className="text-muted-foreground">
<Icon aria-hidden="true" />
</span>
<span className="text-xs font-medium">{app.name}</span>
</DropdownMenuItem>
)
}
return (
<DropdownMenuItem
key={app.id}
render={<a href={app.url} />}
className="h-auto flex-col gap-1.5 py-3 text-center [&_svg]:size-5"
>
<span className="text-muted-foreground">
<Icon aria-hidden="true" />
</span>
<span className="text-xs font-medium">{app.name}</span>
</DropdownMenuItem>
)
})}
</div>
{portalAppsUrl ? (
<>
<DropdownMenuSeparator />
<DropdownMenuItem
render={<a href={portalAppsUrl} />}
className="justify-center text-sm font-medium"
>
Настроить на портале
</DropdownMenuItem>
</>
) : null}
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
)
}