mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
91 lines
2 KiB
TypeScript
91 lines
2 KiB
TypeScript
import {
|
|
rem,
|
|
ActionIcon,
|
|
Tooltip,
|
|
Card,
|
|
Stack,
|
|
Group,
|
|
Text,
|
|
} from '@mantine/core';
|
|
import { Copy } from 'lucide-react';
|
|
import { safeExecute } from '@/utils/logger';
|
|
|
|
export interface InfoItem {
|
|
label: string;
|
|
value: string;
|
|
}
|
|
|
|
interface InfoCardProps {
|
|
title: string;
|
|
items: InfoItem[];
|
|
loading?: boolean;
|
|
}
|
|
|
|
export const InfoCard = ({ title, items, loading = false }: InfoCardProps) => {
|
|
const copyInfo = async () => {
|
|
const info = items.map((item) => `${item.label}: ${item.value}`).join('\n');
|
|
|
|
await safeExecute(
|
|
() => navigator.clipboard.writeText(info),
|
|
`Failed to copy ${title.toLowerCase()}`
|
|
);
|
|
};
|
|
|
|
if (loading) {
|
|
return (
|
|
<Card withBorder radius="md" p="xs">
|
|
<Text size="md" fw={600} mb="sm">
|
|
{title}
|
|
</Text>
|
|
<Text size="sm" c="dimmed">
|
|
Loading...
|
|
</Text>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Card withBorder radius="md" p="xs" style={{ position: 'relative' }}>
|
|
<Tooltip label="Copy">
|
|
<ActionIcon
|
|
variant="subtle"
|
|
size="sm"
|
|
onClick={copyInfo}
|
|
aria-label={`Copy ${title}`}
|
|
style={{
|
|
position: 'absolute',
|
|
top: 8,
|
|
right: 8,
|
|
zIndex: 1,
|
|
}}
|
|
>
|
|
<Copy style={{ width: rem(14), height: rem(14) }} />
|
|
</ActionIcon>
|
|
</Tooltip>
|
|
|
|
<Text size="md" fw={600} mb="sm">
|
|
{title}
|
|
</Text>
|
|
|
|
<Stack gap="xs">
|
|
{items.map((item, index) => (
|
|
<Group key={index} gap="md" align="center" wrap="nowrap">
|
|
<Text size="sm" fw={500} c="dimmed" style={{ minWidth: '7.5rem' }}>
|
|
{item.label}:
|
|
</Text>
|
|
<Text
|
|
size="sm"
|
|
ff="monospace"
|
|
style={{
|
|
wordBreak: 'break-all',
|
|
flex: 1,
|
|
}}
|
|
>
|
|
{item.value}
|
|
</Text>
|
|
</Group>
|
|
))}
|
|
</Stack>
|
|
</Card>
|
|
);
|
|
};
|