175 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react'
import { Box } from '@chakra-ui/react'
import { motion } from 'framer-motion'
import { User, Reaction } from '../../__data__/model'
import { UserCard } from '../user-card'
import { StudentCardBack } from './StudentCardBack'
import { useColorMode } from '@chakra-ui/react'
// Компонент маленькой батарейки для отображения в углу карточки
const BatteryIndicator: React.FC<{
student: User & { present?: boolean; recentlyPresent?: boolean }
}> = ({ student }) => {
const { colorMode } = useColorMode();
// Та же логика из StudentCardBack для определения уровня батареи
const getAttendanceLevel = () => {
if (student.present) {
return student.recentlyPresent ? 4 : 5;
}
const id = student.sub || '';
const idSum = id.split('').reduce((sum, char) => sum + char.charCodeAt(0), 0);
return Math.min(3, Math.floor((idSum % 100) / 25));
}
const batteryLevel = getAttendanceLevel();
// Цвета для разных уровней заряда батареи
const colors = [
// Empty (0)
{ primary: colorMode === "light" ? "#E53E3E" : "#F56565" },
// Very Low (1)
{ primary: colorMode === "light" ? "#DD6B20" : "#ED8936" },
// Low (2)
{ primary: colorMode === "light" ? "#D69E2E" : "#ECC94B" },
// Medium (3)
{ primary: colorMode === "light" ? "#38B2AC" : "#4FD1C5" },
// Good (4)
{ primary: colorMode === "light" ? "#3182CE" : "#4299E1" },
// Excellent (5)
{ primary: colorMode === "light" ? "#38A169" : "#48BB78" }
];
const color = colors[batteryLevel].primary;
// Функция для определения заполненности сегментов
const getSegmentFill = (segmentIndex: number) => {
return segmentIndex <= batteryLevel ? color : 'transparent';
}
return (
<Box
position="absolute"
top="8px"
right="8px"
width="20px"
height="10px"
zIndex="1"
>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
{/* Battery outline */}
<rect
x="2"
y="6"
width="18"
height="12"
rx="2"
stroke={color}
strokeWidth="1.5"
fill="transparent"
/>
{/* Battery cap */}
<path
d="M20 10H22V14H20V10Z"
fill={color}
/>
{/* Battery segments */}
<rect x="4" y="8" width="2.3" height="8" rx="1" fill={getSegmentFill(0)} />
<rect x="7" y="8" width="2.3" height="8" rx="1" fill={getSegmentFill(1)} />
<rect x="10" y="8" width="2.3" height="8" rx="1" fill={getSegmentFill(2)} />
<rect x="13" y="8" width="2.3" height="8" rx="1" fill={getSegmentFill(3)} />
<rect x="16" y="8" width="2.3" height="8" rx="1" fill={getSegmentFill(4)} />
{/* Lightning icon if recently joined or fully charged */}
{(student.recentlyPresent || batteryLevel === 5) && (
<path
d="M11.5 7.5L8 12H11L9.5 16.5L13 12H10L11.5 7.5Z"
fill={color}
stroke={color}
strokeWidth="0.3"
opacity="0.9"
/>
)}
</svg>
</Box>
);
};
interface StudentCardProps {
student: User & { present?: boolean; recentlyPresent?: boolean }
onAddUser: (user: User) => void
reaction?: Reaction
}
export const StudentCard: React.FC<StudentCardProps> = ({
student,
onAddUser,
reaction
}) => {
return (
<motion.li
key={student.sub}
animate={{
rotateY: student.present ? 0 : 180,
boxShadow: student.recentlyPresent
? ['0 0 0 0 rgba(66, 153, 225, 0)', '0 0 20px 5px rgba(66, 153, 225, 0.7)', '0 0 0 0 rgba(66, 153, 225, 0)']
: '0 0 0 0 rgba(0, 0, 0, 0)'
}}
transition={{
rotateY: { type: "spring", stiffness: 300, damping: 20 },
boxShadow: {
repeat: student.recentlyPresent ? 3 : 0,
duration: 1.5
}
}}
style={{
transformStyle: "preserve-3d",
perspective: "1000px",
aspectRatio: "1",
width: "100%",
display: "block"
}}
>
{/* Container for 3D effect */}
<Box
position="relative"
width="100%"
height="100%"
style={{
transformStyle: "preserve-3d"
}}
>
{/* Front side - visible when present */}
<Box
position="absolute"
top="0"
left="0"
width="100%"
height="100%"
style={{
backfaceVisibility: "hidden",
transform: "rotateY(0deg)",
zIndex: student.present ? 1 : 0
}}
>
<UserCard
wrapperAS="div"
student={student}
present={student.present}
recentlyPresent={student.recentlyPresent}
onAddUser={onAddUser}
reaction={reaction}
/>
{/* Battery indicator in corner */}
<BatteryIndicator student={student} />
</Box>
{/* Back side */}
<StudentCardBack student={student} />
</Box>
</motion.li>
)
}