84 lines
1.9 KiB
TypeScript
84 lines
1.9 KiB
TypeScript
import { Avatar, Badge, Card, Group, Loader, Stack, Text } from '@mantine/core'
|
||
import type { UseQueryResult } from '@tanstack/react-query'
|
||
|
||
export type User = {
|
||
id: string
|
||
name: string
|
||
email: string
|
||
role: string
|
||
status: 'active' | 'away' | 'offline'
|
||
}
|
||
|
||
const STATUS_COLOR: Record<User['status'], string> = {
|
||
active: 'green',
|
||
away: 'yellow',
|
||
offline: 'gray',
|
||
}
|
||
|
||
export type UserCardProps = {
|
||
query: UseQueryResult<User | null>
|
||
}
|
||
|
||
export const UserCard: React.FC<UserCardProps> = ({ query }) => {
|
||
if (query.isLoading) {
|
||
return (
|
||
<Card withBorder radius="md" padding="lg">
|
||
<Group>
|
||
<Loader size="sm" />
|
||
<Text size="sm" c="dimmed">
|
||
Loading user…
|
||
</Text>
|
||
</Group>
|
||
</Card>
|
||
)
|
||
}
|
||
|
||
if (query.isError) {
|
||
return (
|
||
<Card withBorder radius="md" padding="lg">
|
||
<Stack gap={4}>
|
||
<Text fw={600} c="red">
|
||
Couldn’t load user
|
||
</Text>
|
||
<Text size="sm" c="dimmed">
|
||
{query.error instanceof Error ? query.error.message : 'Unknown error'}
|
||
</Text>
|
||
</Stack>
|
||
</Card>
|
||
)
|
||
}
|
||
|
||
const user = query.data
|
||
if (!user) {
|
||
return (
|
||
<Card withBorder radius="md" padding="lg">
|
||
<Text size="sm" c="dimmed">
|
||
No user to show.
|
||
</Text>
|
||
</Card>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<Card withBorder radius="md" padding="lg">
|
||
<Group justify="space-between" wrap="nowrap">
|
||
<Group wrap="nowrap">
|
||
<Avatar color="initials" name={user.name} radius="xl" />
|
||
<Stack gap={0}>
|
||
<Text fw={600}>{user.name}</Text>
|
||
<Text size="sm" c="dimmed">
|
||
{user.email}
|
||
</Text>
|
||
</Stack>
|
||
</Group>
|
||
<Badge color={STATUS_COLOR[user.status]} variant="light">
|
||
{user.status}
|
||
</Badge>
|
||
</Group>
|
||
<Text size="sm" mt="md">
|
||
{user.role}
|
||
</Text>
|
||
</Card>
|
||
)
|
||
}
|