mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-03 07:06:36 +08:00
63cd906cfc
- Merge all files inside openflare-server to the repository root directory. - Relocate agent, relay, and flared subprojects from internal/ to internal/apps/. - Combine docker-compose files and update build context paths to root. - Update GitHub workflows and Dockerfiles to refer to new directories and package names. - Rewrite Go package imports across all files. - Resolve database renew test race condition and clean up docs.
79 lines
2.0 KiB
TypeScript
79 lines
2.0 KiB
TypeScript
'use client';
|
|
|
|
import type {ReactNode} from 'react';
|
|
import type {LucideIcon} from 'lucide-react';
|
|
|
|
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from '@/components/ui/card';
|
|
import {cn} from '@/lib/utils';
|
|
|
|
export function NodeInfoRow({
|
|
label,
|
|
children,
|
|
className,
|
|
}: {
|
|
label: string;
|
|
children: ReactNode;
|
|
className?: string;
|
|
}) {
|
|
return (
|
|
<div className={cn('flex items-start justify-between gap-4 py-2.5 text-sm', className)}>
|
|
<span className="shrink-0 text-muted-foreground">{label}</span>
|
|
<div className="min-w-0 text-right font-medium">{children}</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function NodeKpiCard({
|
|
label,
|
|
value,
|
|
icon: Icon,
|
|
}: {
|
|
label: string;
|
|
value: ReactNode;
|
|
icon?: LucideIcon;
|
|
}) {
|
|
return (
|
|
<div className="rounded-xl border bg-card/60 px-4 py-3.5 backdrop-blur-sm">
|
|
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
|
{Icon ? <Icon className="size-3.5 opacity-70" /> : null}
|
|
<span>{label}</span>
|
|
</div>
|
|
<p className="mt-2 text-sm font-semibold tracking-tight break-all">{value}</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function NodeSectionCard({
|
|
title,
|
|
description,
|
|
action,
|
|
children,
|
|
className,
|
|
}: {
|
|
title: string;
|
|
description?: string;
|
|
action?: React.ReactNode;
|
|
children: ReactNode;
|
|
className?: string;
|
|
}) {
|
|
return (
|
|
<Card className={cn('border shadow-none', className)}>
|
|
<CardHeader className={cn('pb-3', action ? 'flex-row items-start justify-between space-y-0' : '')}>
|
|
<div className="space-y-1">
|
|
<CardTitle className="text-base font-semibold">{title}</CardTitle>
|
|
{description ? <CardDescription>{description}</CardDescription> : null}
|
|
</div>
|
|
{action}
|
|
</CardHeader>
|
|
<CardContent>{children}</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
export function NodeErrorBanner({ message }: { message: string }) {
|
|
return (
|
|
<div className="rounded-xl border border-destructive/25 bg-destructive/5 px-4 py-3 text-sm text-destructive">
|
|
{message}
|
|
</div>
|
|
);
|
|
} |