From a3f3ffd67272e8ed21a138d6ab1a45320fdd5ec1 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Thu, 9 Jul 2026 21:39:20 +0700 Subject: [PATCH] refactor: integrate PanelCard and enhance dashboard components for improved layout Refactored multiple dashboard components to utilize the new PanelCard for better organization and presentation. Updated the DashboardFramePanel, DashboardQuickLinks, and DashboardOperationsBreakdown components to streamline layouts and enhance user experience. Removed deprecated components and improved loading states in various sections, ensuring a cohesive interface throughout the application. --- .../analytics/monitoring-health-card.tsx | 33 +- .../network-overview-analytics-card.tsx | 84 +- .../app-shell-7/components/app-header.tsx | 220 ++++ .../app-shell-7/components/app-shell.tsx | 43 + .../app-shell-7/components/app-sidebar.tsx | 51 + .../blocks/app-shell-7/components/data.tsx | 385 ++++++ .../blocks/app-shell-7/components/logo.tsx | 29 + .../app-shell-7/components/nav-main.tsx | 122 ++ .../app-shell-7/components/nav-user.tsx | 202 +++ .../app-shell-7/components/search-form.tsx | 78 ++ .../app-shell-7/components/sidebar-news.tsx | 281 +++++ .../components/sidebar-rail-toggle.tsx | 61 + .../app-shell-7/components/system-stats.tsx | 441 +++++++ .../components/blocks/app-shell-7/page.tsx | 5 + .../blocks/chart-12/components/chart.tsx | 240 ++++ .../blocks/chart-12/components/data.tsx | 147 +++ .../src/components/blocks/chart-12/page.tsx | 9 + .../blocks/chart-13/components/chart.tsx | 262 ++++ .../blocks/chart-13/components/data.ts | 141 +++ .../src/components/blocks/chart-13/page.tsx | 9 + .../blocks/chart-15/components/chart.tsx | 154 +++ .../blocks/chart-15/components/data.tsx | 70 ++ .../src/components/blocks/chart-15/page.tsx | 9 + .../blocks/chart-27/components/chart.tsx | 158 +++ .../blocks/chart-27/components/data.ts | 51 + .../src/components/blocks/chart-27/page.tsx | 9 + .../data-grid-base-6/components/columns.tsx | 241 ++++ .../components/data-grid-view.tsx | 426 +++++++ .../data-grid-base-6/components/data.tsx | 154 +++ .../blocks/data-grid-base-6/page.tsx | 15 + .../components/columns.tsx | 512 ++++++++ .../components/data-grid-view.tsx | 691 ++++++++++ .../data-grid-expansion-3/components/data.tsx | 1110 +++++++++++++++++ .../components/release-check-rail.tsx | 212 ++++ .../components/release-review-card.tsx | 60 + .../blocks/data-grid-expansion-3/page.tsx | 15 + .../components/columns.tsx | 426 +++++++ .../components/data-grid-view.tsx | 597 +++++++++ .../data-grid-filtering-1/components/data.tsx | 263 ++++ .../blocks/data-grid-filtering-1/page.tsx | 15 + .../components/columns.tsx | 408 ++++++ .../components/data-grid-view.tsx | 660 ++++++++++ .../data-grid-filtering-2/components/data.tsx | 384 ++++++ .../blocks/data-grid-filtering-2/page.tsx | 15 + .../components/columns.tsx | 685 ++++++++++ .../components/data-grid-view.tsx | 766 ++++++++++++ .../data-grid-filtering-3/components/data.tsx | 738 +++++++++++ .../components/renewal-selection-bar.tsx | 108 ++ .../components/renewals-command-card.tsx | 63 + .../blocks/data-grid-filtering-3/page.tsx | 33 + .../empty-state-11/components/empty-state.tsx | 58 + .../components/blocks/empty-state-11/page.tsx | 15 + .../empty-state-3/components/empty-state.tsx | 55 + .../projects-empty-illustration.tsx | 325 +++++ .../components/quick-start-templates.tsx | 54 + .../components/blocks/empty-state-3/page.tsx | 9 + .../blocks/schedule-1/components/data.ts | 380 ++++++ .../schedule-1/components/event-card.tsx | 79 ++ .../schedule-1/components/events-list.tsx | 135 ++ .../components/schedule-calendar.tsx | 190 +++ .../blocks/schedule-1/components/schedule.tsx | 45 + .../src/components/blocks/schedule-1/page.tsx | 9 + .../components/api-integrations-grid.tsx | 151 +++ .../blocks/settings-14/components/columns.tsx | 222 ++++ .../blocks/settings-14/components/data.tsx | 345 +++++ .../components/blocks/settings-14/page.tsx | 9 + .../settings-3/components/color-picker.tsx | 42 + .../blocks/settings-3/components/data.tsx | 107 ++ .../components/editor-preferences.tsx | 59 + .../components/general-settings.tsx | 265 ++++ .../settings-3/components/setting-field.tsx | 71 ++ .../src/components/blocks/settings-3/page.tsx | 9 + .../blocks/stats-4/components/data.ts | 16 + .../blocks/stats-4/components/stats.tsx | 131 ++ .../src/components/blocks/stats-4/page.tsx | 9 + .../blocks/stats-6/components/data.ts | 35 + .../blocks/stats-6/components/stats.tsx | 186 +++ .../src/components/blocks/stats-6/page.tsx | 9 + .../dashboard/dashboard-frame-panel.tsx | 33 +- .../dashboard/dashboard-kpi-grid.tsx | 182 --- .../dashboard/dashboard-kpi-sparkline-row.tsx | 118 ++ .../dashboard/dashboard-network-health.tsx | 62 +- .../dashboard-operations-breakdown.tsx | 45 +- .../dashboard/dashboard-quick-link-card.tsx | 11 +- .../dashboard/dashboard-quick-links.tsx | 28 +- apps/web/src/components/layout/app-shell.tsx | 202 +-- .../src/components/layout/command-palette.tsx | 143 +++ .../layout/system-monitor-popover.tsx | 213 ++++ .../components/modules/module-kpi-cards.tsx | 96 +- .../components/network/network-peers-card.tsx | 50 +- .../operations/operations-jobs-card.tsx | 86 ++ .../patterns/donut-breakdown-card.tsx | 92 ++ .../patterns/illustrated-empty-state.tsx | 46 + apps/web/src/components/patterns/index.ts | 6 + .../patterns/kpi-sparkline-card.tsx | 77 ++ .../components/patterns/metric-tone-styles.ts | 8 + .../src/components/patterns/panel-corners.tsx | 15 + .../patterns/projects-empty-state.tsx | 22 + .../patterns/segmented-progress-card.tsx | 70 ++ apps/web/src/components/query-state.tsx | 3 + .../data-grid/data-grid-column-filter.tsx | 2 - .../data-grid/data-grid-column-header.tsx | 2 + .../data-grid/data-grid-column-visibility.tsx | 2 - .../reui/data-grid/data-grid-pagination.tsx | 2 + .../reui/data-grid/data-grid-scroll-area.tsx | 2 - .../data-grid/data-grid-table-dnd-rows.tsx | 2 + .../reui/data-grid/data-grid-table-dnd.tsx | 2 - .../data-grid/data-grid-table-virtual.tsx | 2 + .../reui/data-grid/data-grid-table.tsx | 2 - .../components/reui/data-grid/data-grid.tsx | 2 + apps/web/src/components/reui/filters.tsx | 9 +- apps/web/src/components/reui/icon-stack.tsx | 90 ++ apps/web/src/components/reui/rating.tsx | 166 +++ .../schedule/schedule-agenda-panel.tsx | 91 ++ .../settings/settings-setting-field.tsx | 57 + apps/web/src/components/skeletons.tsx | 31 +- .../src/components/ui/svgs/anthropicBlack.tsx | 15 + .../src/components/ui/svgs/anthropicWhite.tsx | 16 + apps/web/src/components/ui/svgs/convex.tsx | 20 + apps/web/src/components/ui/svgs/discord.tsx | 12 + apps/web/src/components/ui/svgs/gemini.tsx | 171 +++ .../src/components/ui/svgs/googleCloud.tsx | 24 + apps/web/src/components/ui/svgs/hono.tsx | 17 + apps/web/src/components/ui/svgs/loom.tsx | 12 + apps/web/src/components/ui/svgs/mintlify.tsx | 20 + apps/web/src/components/ui/svgs/n8n.tsx | 14 + apps/web/src/components/ui/svgs/neon.tsx | 35 + apps/web/src/components/ui/svgs/openai.tsx | 9 + .../web/src/components/ui/svgs/openaiDark.tsx | 12 + apps/web/src/components/ui/svgs/paper.tsx | 9 + .../src/components/ui/svgs/planetscale.tsx | 9 + .../components/ui/svgs/planetscaleDark.tsx | 12 + apps/web/src/components/ui/svgs/prisma.tsx | 9 + .../web/src/components/ui/svgs/prismaDark.tsx | 12 + apps/web/src/components/ui/svgs/remixDark.tsx | 12 + .../web/src/components/ui/svgs/remixLight.tsx | 12 + .../components/ui/svgs/resendIconBlack.tsx | 12 + .../components/ui/svgs/resendIconWhite.tsx | 12 + apps/web/src/components/ui/svgs/slack.tsx | 26 + apps/web/src/components/ui/svgs/stripe.tsx | 14 + apps/web/src/components/ui/svgs/supabase.tsx | 45 + apps/web/src/components/ui/svgs/zoom.tsx | 39 + apps/web/src/hooks/use-copy-to-clipboard.ts | 37 + apps/web/src/hooks/use-mobile.ts | 19 + apps/web/src/lib/ui-surface.ts | 26 + apps/web/src/routes/_auth/dashboard.tsx | 9 +- apps/web/src/routes/_auth/modules/index.tsx | 4 +- apps/web/src/routes/_auth/monitoring.tsx | 126 +- apps/web/src/routes/_auth/operations.tsx | 31 +- apps/web/src/routes/_auth/schedule.tsx | 3 + apps/web/src/routes/_auth/tenant-settings.tsx | 20 +- apps/web/tsconfig.tsbuildinfo | 2 +- packages/ui/src/components/chart.tsx | 2 + packages/ui/src/components/dialog.tsx | 2 - packages/ui/src/components/empty.tsx | 104 ++ packages/ui/src/components/field.tsx | 2 - packages/ui/src/components/label.tsx | 2 - packages/ui/src/components/progress.tsx | 2 + packages/ui/src/components/switch.tsx | 30 + packages/ui/src/components/tabs.tsx | 8 +- packages/ui/src/components/toggle-group.tsx | 89 ++ 161 files changed, 17496 insertions(+), 605 deletions(-) create mode 100644 apps/web/src/components/blocks/app-shell-7/components/app-header.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/app-shell.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/app-sidebar.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/data.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/logo.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/nav-main.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/nav-user.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/search-form.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/sidebar-news.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/sidebar-rail-toggle.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/components/system-stats.tsx create mode 100644 apps/web/src/components/blocks/app-shell-7/page.tsx create mode 100644 apps/web/src/components/blocks/chart-12/components/chart.tsx create mode 100644 apps/web/src/components/blocks/chart-12/components/data.tsx create mode 100644 apps/web/src/components/blocks/chart-12/page.tsx create mode 100644 apps/web/src/components/blocks/chart-13/components/chart.tsx create mode 100644 apps/web/src/components/blocks/chart-13/components/data.ts create mode 100644 apps/web/src/components/blocks/chart-13/page.tsx create mode 100644 apps/web/src/components/blocks/chart-15/components/chart.tsx create mode 100644 apps/web/src/components/blocks/chart-15/components/data.tsx create mode 100644 apps/web/src/components/blocks/chart-15/page.tsx create mode 100644 apps/web/src/components/blocks/chart-27/components/chart.tsx create mode 100644 apps/web/src/components/blocks/chart-27/components/data.ts create mode 100644 apps/web/src/components/blocks/chart-27/page.tsx create mode 100644 apps/web/src/components/blocks/data-grid-base-6/components/columns.tsx create mode 100644 apps/web/src/components/blocks/data-grid-base-6/components/data-grid-view.tsx create mode 100644 apps/web/src/components/blocks/data-grid-base-6/components/data.tsx create mode 100644 apps/web/src/components/blocks/data-grid-base-6/page.tsx create mode 100644 apps/web/src/components/blocks/data-grid-expansion-3/components/columns.tsx create mode 100644 apps/web/src/components/blocks/data-grid-expansion-3/components/data-grid-view.tsx create mode 100644 apps/web/src/components/blocks/data-grid-expansion-3/components/data.tsx create mode 100644 apps/web/src/components/blocks/data-grid-expansion-3/components/release-check-rail.tsx create mode 100644 apps/web/src/components/blocks/data-grid-expansion-3/components/release-review-card.tsx create mode 100644 apps/web/src/components/blocks/data-grid-expansion-3/page.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-1/components/columns.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-1/components/data-grid-view.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-1/components/data.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-1/page.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-2/components/columns.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-2/components/data-grid-view.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-2/components/data.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-2/page.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-3/components/columns.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-3/components/data-grid-view.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-3/components/data.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-3/components/renewal-selection-bar.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-3/components/renewals-command-card.tsx create mode 100644 apps/web/src/components/blocks/data-grid-filtering-3/page.tsx create mode 100644 apps/web/src/components/blocks/empty-state-11/components/empty-state.tsx create mode 100644 apps/web/src/components/blocks/empty-state-11/page.tsx create mode 100644 apps/web/src/components/blocks/empty-state-3/components/empty-state.tsx create mode 100644 apps/web/src/components/blocks/empty-state-3/components/projects-empty-illustration.tsx create mode 100644 apps/web/src/components/blocks/empty-state-3/components/quick-start-templates.tsx create mode 100644 apps/web/src/components/blocks/empty-state-3/page.tsx create mode 100644 apps/web/src/components/blocks/schedule-1/components/data.ts create mode 100644 apps/web/src/components/blocks/schedule-1/components/event-card.tsx create mode 100644 apps/web/src/components/blocks/schedule-1/components/events-list.tsx create mode 100644 apps/web/src/components/blocks/schedule-1/components/schedule-calendar.tsx create mode 100644 apps/web/src/components/blocks/schedule-1/components/schedule.tsx create mode 100644 apps/web/src/components/blocks/schedule-1/page.tsx create mode 100644 apps/web/src/components/blocks/settings-14/components/api-integrations-grid.tsx create mode 100644 apps/web/src/components/blocks/settings-14/components/columns.tsx create mode 100644 apps/web/src/components/blocks/settings-14/components/data.tsx create mode 100644 apps/web/src/components/blocks/settings-14/page.tsx create mode 100644 apps/web/src/components/blocks/settings-3/components/color-picker.tsx create mode 100644 apps/web/src/components/blocks/settings-3/components/data.tsx create mode 100644 apps/web/src/components/blocks/settings-3/components/editor-preferences.tsx create mode 100644 apps/web/src/components/blocks/settings-3/components/general-settings.tsx create mode 100644 apps/web/src/components/blocks/settings-3/components/setting-field.tsx create mode 100644 apps/web/src/components/blocks/settings-3/page.tsx create mode 100644 apps/web/src/components/blocks/stats-4/components/data.ts create mode 100644 apps/web/src/components/blocks/stats-4/components/stats.tsx create mode 100644 apps/web/src/components/blocks/stats-4/page.tsx create mode 100644 apps/web/src/components/blocks/stats-6/components/data.ts create mode 100644 apps/web/src/components/blocks/stats-6/components/stats.tsx create mode 100644 apps/web/src/components/blocks/stats-6/page.tsx delete mode 100644 apps/web/src/components/dashboard/dashboard-kpi-grid.tsx create mode 100644 apps/web/src/components/dashboard/dashboard-kpi-sparkline-row.tsx create mode 100644 apps/web/src/components/layout/command-palette.tsx create mode 100644 apps/web/src/components/layout/system-monitor-popover.tsx create mode 100644 apps/web/src/components/operations/operations-jobs-card.tsx create mode 100644 apps/web/src/components/patterns/donut-breakdown-card.tsx create mode 100644 apps/web/src/components/patterns/illustrated-empty-state.tsx create mode 100644 apps/web/src/components/patterns/index.ts create mode 100644 apps/web/src/components/patterns/kpi-sparkline-card.tsx create mode 100644 apps/web/src/components/patterns/metric-tone-styles.ts create mode 100644 apps/web/src/components/patterns/panel-corners.tsx create mode 100644 apps/web/src/components/patterns/projects-empty-state.tsx create mode 100644 apps/web/src/components/patterns/segmented-progress-card.tsx create mode 100644 apps/web/src/components/reui/icon-stack.tsx create mode 100644 apps/web/src/components/reui/rating.tsx create mode 100644 apps/web/src/components/schedule/schedule-agenda-panel.tsx create mode 100644 apps/web/src/components/settings/settings-setting-field.tsx create mode 100644 apps/web/src/components/ui/svgs/anthropicBlack.tsx create mode 100644 apps/web/src/components/ui/svgs/anthropicWhite.tsx create mode 100644 apps/web/src/components/ui/svgs/convex.tsx create mode 100644 apps/web/src/components/ui/svgs/discord.tsx create mode 100644 apps/web/src/components/ui/svgs/gemini.tsx create mode 100644 apps/web/src/components/ui/svgs/googleCloud.tsx create mode 100644 apps/web/src/components/ui/svgs/hono.tsx create mode 100644 apps/web/src/components/ui/svgs/loom.tsx create mode 100644 apps/web/src/components/ui/svgs/mintlify.tsx create mode 100644 apps/web/src/components/ui/svgs/n8n.tsx create mode 100644 apps/web/src/components/ui/svgs/neon.tsx create mode 100644 apps/web/src/components/ui/svgs/openai.tsx create mode 100644 apps/web/src/components/ui/svgs/openaiDark.tsx create mode 100644 apps/web/src/components/ui/svgs/paper.tsx create mode 100644 apps/web/src/components/ui/svgs/planetscale.tsx create mode 100644 apps/web/src/components/ui/svgs/planetscaleDark.tsx create mode 100644 apps/web/src/components/ui/svgs/prisma.tsx create mode 100644 apps/web/src/components/ui/svgs/prismaDark.tsx create mode 100644 apps/web/src/components/ui/svgs/remixDark.tsx create mode 100644 apps/web/src/components/ui/svgs/remixLight.tsx create mode 100644 apps/web/src/components/ui/svgs/resendIconBlack.tsx create mode 100644 apps/web/src/components/ui/svgs/resendIconWhite.tsx create mode 100644 apps/web/src/components/ui/svgs/slack.tsx create mode 100644 apps/web/src/components/ui/svgs/stripe.tsx create mode 100644 apps/web/src/components/ui/svgs/supabase.tsx create mode 100644 apps/web/src/components/ui/svgs/zoom.tsx create mode 100644 apps/web/src/hooks/use-copy-to-clipboard.ts create mode 100644 apps/web/src/hooks/use-mobile.ts create mode 100644 apps/web/src/lib/ui-surface.ts create mode 100644 packages/ui/src/components/empty.tsx create mode 100644 packages/ui/src/components/switch.tsx create mode 100644 packages/ui/src/components/toggle-group.tsx diff --git a/apps/web/src/components/analytics/monitoring-health-card.tsx b/apps/web/src/components/analytics/monitoring-health-card.tsx index aac7c89..c884d7e 100644 --- a/apps/web/src/components/analytics/monitoring-health-card.tsx +++ b/apps/web/src/components/analytics/monitoring-health-card.tsx @@ -1,5 +1,4 @@ -import { AnalyticsCardShell } from '@/components/analytics/analytics-card-shell' -import { ChartDonutMetric } from '@/components/analytics/chart-donut-metric' +import { DonutBreakdownCard } from '@/components/patterns/donut-breakdown-card' import { readinessBreakdown } from '@/lib/metrics' import type { ReadyStatus } from '@/queries/monitoring' @@ -13,21 +12,25 @@ export function MonitoringHealthCard({ loading?: boolean }) { const slices = readinessBreakdown(ready, healthOk) - const total = slices.reduce((sum, slice) => sum + slice.count, 0) + + if (loading) { + return ( + + ) + } return ( - - {loading ? ( -
- Загрузка… -
- ) : ( - - )} -
+ description="GET /v1/health · GET /v1/ready" + slices={slices} + centerLabel="Проверки" + badge={healthOk ? 'API OK' : undefined} + /> ) } diff --git a/apps/web/src/components/analytics/network-overview-analytics-card.tsx b/apps/web/src/components/analytics/network-overview-analytics-card.tsx index 51968e5..868074d 100644 --- a/apps/web/src/components/analytics/network-overview-analytics-card.tsx +++ b/apps/web/src/components/analytics/network-overview-analytics-card.tsx @@ -1,6 +1,5 @@ -import { AnalyticsCardShell } from '@/components/analytics/analytics-card-shell' -import { AnalyticsKpiRow } from '@/components/analytics/analytics-kpi-row' -import { ChartDonutMetric } from '@/components/analytics/chart-donut-metric' +import { DonutBreakdownCard } from '@/components/patterns/donut-breakdown-card' +import { SegmentedProgressCard } from '@/components/patterns/segmented-progress-card' import { peerSessionBreakdown } from '@/lib/metrics' import { aggregateNetworkMetrics } from '@/queries/overview' import type { PeerRow, SpeakerRow } from '@/types/api' @@ -16,51 +15,44 @@ export function NetworkOverviewAnalyticsCard({ }) { const net = aggregateNetworkMetrics(peers, speakers) const slices = peerSessionBreakdown(peers) - const total = slices.reduce((sum, slice) => sum + slice.count, 0) + const speakersPct = + net.speakersTotal > 0 ? Math.round((net.speakersOnline / net.speakersTotal) * 100) : 0 + + if (loading) { + return ( + + ) + } return ( - - 0 ? 'down' : 'up', - label: net.peersMismatch > 0 ? `${net.peersMismatch} расхождений` : 'сессии в норме', - tone: net.peersMismatch > 0 ? 'warning' : 'success', - }, - }, - { - label: 'Спикеры в сети', - value: loading ? '—' : `${net.speakersOnline}/${net.speakersTotal}`, - delta: { - direction: net.speakersOnline < net.speakersTotal ? 'down' : 'up', - label: - net.speakersOnline < net.speakersTotal - ? `${net.speakersTotal - net.speakersOnline} не в сети` - : 'все в сети', - tone: net.speakersOnline < net.speakersTotal ? 'warning' : 'success', - }, - }, - { - label: 'Пиры всего', - value: loading ? '—' : String(net.peersTotal), - delta: { direction: 'neutral', label: 'в каталоге', tone: 'muted' }, - }, - ]} +
+ 0 ? `${net.peersMismatch} расхождений` : 'в норме'} /> - {loading ? ( -
- Загрузка… -
- ) : ( - - )} - + +
) } diff --git a/apps/web/src/components/blocks/app-shell-7/components/app-header.tsx b/apps/web/src/components/blocks/app-shell-7/components/app-header.tsx new file mode 100644 index 0000000..3d2d858 --- /dev/null +++ b/apps/web/src/components/blocks/app-shell-7/components/app-header.tsx @@ -0,0 +1,220 @@ +"use client" + +import { useState } from "react" + +import { cn } from "@evobgp/ui/lib/utils" +import { + Breadcrumb, + BreadcrumbItem, + BreadcrumbList, + BreadcrumbSeparator, +} from "@evobgp/ui/components/breadcrumb" +import { Button } from "@evobgp/ui/components/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@evobgp/ui/components/dropdown-menu" +import { SidebarTrigger } from "@evobgp/ui/components/sidebar" +import { APPS, ENVIRONMENTS, WORKSPACES } from "./data" +import { Logo } from "./logo" +import { SystemStats } from "./system-stats" +import { ChevronsUpDownIcon, CheckIcon, PlusIcon } from "lucide-react" + +// ── Org Switcher ── + +function OrgSwitcher() { + const [activeOrg, setActiveOrg] = useState(WORKSPACES[0]) + + return ( + + + } + > + + {activeOrg.name} + + + + + Organizations + + {WORKSPACES.map((ws) => ( + setActiveOrg(ws)} + className={cn(activeOrg.id === ws.id && "bg-accent")} + > + +
+ {ws.name} + + {ws.tier} + +
+ {activeOrg.id === ws.id && ( +
+ ))} +
+ + + +
+
+
+ ) +} + +// ── App Switcher ── + +function AppSwitcher() { + const [activeApp, setActiveApp] = useState( + APPS.find((a) => a.isActive) ?? APPS[0] + ) + + return ( + + + } + > + {activeApp.name} + {activeApp.name.split(" ")[0]} + + + + + Applications + + {APPS.map((app) => ( + setActiveApp(app)} + className={cn(activeApp.id === app.id && "bg-accent")} + > + {app.icon} + {app.name} + {activeApp.id === app.id && ( + + ))} + + + + + + + + ) +} + +// ── Environment Switcher ── + +function EnvironmentSwitcher() { + const [activeEnv, setActiveEnv] = useState( + ENVIRONMENTS.find((e) => e.isActive) ?? ENVIRONMENTS[0] + ) + + return ( + + + } + > + {activeEnv.name} + + + + + Environments + + {ENVIRONMENTS.map((env) => ( + setActiveEnv(env)} + className={cn(activeEnv.id === env.id && "bg-accent")} + > + {env.icon} + {env.name} + {activeEnv.id === env.id && ( + + ))} + + + + + ) +} + +// ── Site Header ── + +export function AppHeader() { + return ( +
+
+ {/* Mobile sidebar trigger */} + + + {/* Logo */} +
+ +
+ + + + + + + + / + + + + + + / + + + + + + + + {/* Right side */} +
+ +
+
+
+ ) +} \ No newline at end of file diff --git a/apps/web/src/components/blocks/app-shell-7/components/app-shell.tsx b/apps/web/src/components/blocks/app-shell-7/components/app-shell.tsx new file mode 100644 index 0000000..672e1ac --- /dev/null +++ b/apps/web/src/components/blocks/app-shell-7/components/app-shell.tsx @@ -0,0 +1,43 @@ +import { type CSSProperties } from "react" + +import { cn } from "@evobgp/ui/lib/utils" +import { SidebarInset, SidebarProvider } from "@evobgp/ui/components/sidebar" + +import { AppHeader } from "./app-header" +import { AppSidebar } from "./app-sidebar" + +export function AppShell() { + return ( + + {/* Header */} + +
+ + +
+
+
+
+
+
+
+
+ +
+ + ) +} \ No newline at end of file diff --git a/apps/web/src/components/blocks/app-shell-7/components/app-sidebar.tsx b/apps/web/src/components/blocks/app-shell-7/components/app-sidebar.tsx new file mode 100644 index 0000000..13ef614 --- /dev/null +++ b/apps/web/src/components/blocks/app-shell-7/components/app-sidebar.tsx @@ -0,0 +1,51 @@ +import { + Sidebar, + SidebarContent, + SidebarFooter, + SidebarHeader, + useSidebar, +} from "@evobgp/ui/components/sidebar" + +import { NEWS_ARTICLES } from "./data" +import { NavMain } from "./nav-main" +import { NavUser } from "./nav-user" +import { SearchForm } from "./search-form" +import { SidebarNews } from "./sidebar-news" +import { SidebarRailToggle } from "./sidebar-rail-toggle" + +// ── App Sidebar ── + +export function AppSidebar() { + const { isMobile } = useSidebar() + + return ( + + {/* Header */} + +
+ +
+
+ + {/* Sidebar */} + + + +
+ +
+
+ + {/* Footer */} + {/* customize: mt-2 keeps a fixed gap above the footer so the news card never butts against it when the viewport shrinks and the content scrolls */} + + + + + {!isMobile && } +
+ ) +} \ No newline at end of file diff --git a/apps/web/src/components/blocks/app-shell-7/components/data.tsx b/apps/web/src/components/blocks/app-shell-7/components/data.tsx new file mode 100644 index 0000000..f6b9990 --- /dev/null +++ b/apps/web/src/components/blocks/app-shell-7/components/data.tsx @@ -0,0 +1,385 @@ +import { type ComponentType, type ReactNode } from "react" +import { GlobeIcon, ShieldIcon, SmartphoneIcon, RocketIcon, FlaskConicalIcon, CodeIcon, LayoutDashboardIcon, UsersIcon, Building2Icon, ShieldCheckIcon, WebhookIcon, KeyRoundIcon, CpuIcon, MonitorIcon, MemoryStickIcon, WifiIcon } from "lucide-react" + +// ── Types ── + +export type NavChild = { + id: string + label: string + isActive?: boolean +} + +export type NavItem = { + id: string + label: string + icon: ReactNode + badge?: string | number + isActive?: boolean + children?: NavChild[] +} + +export type Workspace = { + id: string + name: string + tier: string + Logo: ComponentType<{ className?: string }> +} + +export type App = { + id: string + name: string + icon: ReactNode + isActive?: boolean +} + +export type Environment = { + id: string + name: string + icon: ReactNode + isActive?: boolean +} + +export type NewsArticle = { + href: string + title: string + summary: string + image: string +} + +export type ResourceMetric = { + id: string + label: string + unit: string + icon: ReactNode + seedRange: [number, number] + color: string + spikeThreshold: number +} + +export type Agent = { + id: string + name: string + memoryMb: number + color: string +} + +// ── Logos ── + +// Acme: indigo → violet → fuchsia diagonal sweep +function AcmeLogo({ className }: { className?: string }) { + return ( + + ) +} + +// Starter: rose → orange → amber → lime horizontal sweep +function StarterLogo({ className }: { className?: string }) { + return ( + + ) +} + +// Enterprise: sky → blue → indigo vertical sweep +function EnterpriseLogo({ className }: { className?: string }) { + return ( + + ) +} + +// ── Data ── + +export const USER = { + name: "Nick Bold", + email: "nick@reui.io", + initials: "NB", + avatar: + "https://images.unsplash.com/photo-1543299750-19d1d6297053?w=96&h=96&dpr=2&q=80", +} as const + +export const WORKSPACES: Workspace[] = [ + { id: "acme", name: "Acme Inc", tier: "Pro", Logo: AcmeLogo }, + { id: "starter", name: "Starter Kit", tier: "Free", Logo: StarterLogo }, + { + id: "enterprise", + name: "Enterprise", + tier: "Enterprise", + Logo: EnterpriseLogo, + }, +] + +export const APPS: App[] = [ + { + id: "web-app", + name: "Web App", + isActive: true, + icon: ( +