journal.pl/src/user-card/user-card.tsx
Primakov Alexandr Alexandrovich 9cbc5910ef
All checks were successful
platform/bro-js/journal.pl/pipeline/head This commit looks good
vibe themes
2025-04-24 17:24:07 +03:00

175 lines
4.1 KiB
TypeScript

import React from 'react';
import { Box, useColorMode, Text } from '@chakra-ui/react';
import { useThemeManager } from '../../hooks/useThemeManager';
interface UserCardProps {
user: {
id: string;
name: string;
photo?: string;
role?: string;
status?: 'online' | 'offline' | 'away';
attendance?: number;
};
onClick?: () => void;
showStatus?: boolean;
showAttendance?: boolean;
}
export const UserCard: React.FC<UserCardProps> = ({
user,
onClick,
showStatus = false,
showAttendance = false
}) => {
const { isLightVariant } = useThemeManager();
// Функция для определения цвета статуса онлайн
const getStatusColor = (status: string) => {
switch (status) {
case 'online':
return 'green.500';
case 'away':
return 'yellow.500';
default:
return 'gray.400';
}
};
// Функция для рендера индикатора посещаемости
const renderAttendanceIndicator = (attendance: number) => {
let color;
let text;
if (attendance >= 90) {
color = 'green.500';
text = '✓✓✓';
} else if (attendance >= 70) {
color = 'green.400';
text = '✓✓';
} else if (attendance >= 50) {
color = 'yellow.500';
text = '✓';
} else if (attendance >= 30) {
color = 'orange.500';
text = '⚠';
} else {
color = 'red.500';
text = '✗';
}
return (
<Text
fontSize="xs"
color={color}
position="absolute"
bottom="8px"
right="8px"
>
{text}
</Text>
);
};
return (
<Box
position="relative"
borderRadius="md"
overflow="hidden"
boxShadow="sm"
transition="transform 0.2s, box-shadow 0.2s"
_hover={onClick ? {
transform: 'translateY(-2px)',
boxShadow: 'md',
cursor: 'pointer'
} : {}}
onClick={onClick}
bg={isLightVariant ? 'white' : 'gray.700'}
p={3}
>
<Box
position="relative"
borderRadius="full"
width="60px"
height="60px"
overflow="hidden"
margin="0 auto 8px"
>
{user.photo ? (
<Box
as="img"
src={user.photo}
alt={user.name}
width="100%"
height="100%"
objectFit="cover"
/>
) : (
<Box
width="100%"
height="100%"
bg="gray.300"
display="flex"
alignItems="center"
justifyContent="center"
fontSize="xl"
fontWeight="bold"
color="gray.600"
>
{user.name.charAt(0).toUpperCase()}
</Box>
)}
{showStatus && user.status && (
<Box
position="absolute"
bottom="2px"
right="2px"
width="12px"
height="12px"
borderRadius="full"
bg={getStatusColor(user.status)}
border="2px solid"
borderColor={isLightVariant ? 'white' : 'gray.700'}
/>
)}
</Box>
<Text
textAlign="center"
fontWeight="medium"
fontSize="sm"
noOfLines={1}
title={user.name}
>
{user.name}
</Text>
{user.role && (
<Text
textAlign="center"
fontSize="xs"
color={isLightVariant ? 'gray.500' : 'gray.300'}
noOfLines={1}
>
{user.role}
</Text>
)}
{showAttendance && typeof user.attendance === 'number' && renderAttendanceIndicator(user.attendance)}
{/* Дополнительные декоративные элементы в зависимости от темы */}
<Box
position="absolute"
top={0}
left={0}
right={0}
height="5px"
background={isLightVariant ? 'rgba(255, 255, 255, 0.8)' : 'rgba(0, 0, 0, 0.6)'}
borderTopLeftRadius="md"
borderTopRightRadius="md"
zIndex={1}
/>
</Box>
);
};