All checks were successful
platform/bro-js/journal.pl/pipeline/head This commit looks good
175 lines
4.1 KiB
TypeScript
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>
|
|
);
|
|
};
|