Упрощено управление реакциями студентов в карточке пользователя. Изменено состояние реакций на использование одного объекта вместо массива, улучшена анимация отображения реакций.

This commit is contained in:
Primakov Alexandr Alexandrovich 2025-03-27 14:14:31 +03:00
parent 56a04dbe14
commit d648a181c3
3 changed files with 31 additions and 47 deletions

View File

@ -6,7 +6,7 @@ import { CheckCircleIcon, AddIcon } from '@chakra-ui/icons'
import { motion, AnimatePresence } from 'framer-motion'
import { useTranslation } from 'react-i18next'
import { User, Reaction } from '../../__data__/model'
import { Reaction, User } from '../../__data__/model'
import { AddMissedButton, Avatar, Wrapper, NameOverlay } from './style'
@ -34,58 +34,45 @@ export const UserCard = ({
wrapperAS = 'div',
width,
recentlyPresent = false,
reactions = []
reaction
}: {
student: User
present: boolean
width?: string | number
onAddUser?: (user: User) => void
wrapperAS?: React.ElementType<any, keyof React.JSX.IntrinsicElements>;
wrapperAS?: React.ElementType<any, keyof React.JSX.IntrinsicElements>
recentlyPresent?: boolean
reactions?: Reaction[]
reaction?: Reaction
}) => {
const { colorMode } = useColorMode();
const { t } = useTranslation();
const [imageError, setImageError] = useState(false);
const [visibleReactions, setVisibleReactions] = useState<Reaction[]>([]);
const [showReaction, setShowReaction] = useState(false);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
// Filter reactions to only show this student's reactions
// Обрабатываем изменение реакции
useEffect(() => {
const studentReactions = reactions.filter(r => r.sub === student.sub);
if (studentReactions.length > 0) {
// Check for new reactions
const newReactions = studentReactions.filter(
newReaction => !visibleReactions.some(
existingReaction => existingReaction._id === newReaction._id
)
);
if (reaction) {
setShowReaction(true);
if (newReactions.length > 0) {
// If there are new reactions, add them to visible reactions
setVisibleReactions(prevReactions => [...prevReactions, ...newReactions]);
// Clear any existing timeout
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
// Set a new timeout
timeoutRef.current = setTimeout(() => {
setVisibleReactions([]);
timeoutRef.current = null;
}, 3000);
// Очищаем предыдущий таймер если он есть
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
// Устанавливаем новый таймер
timeoutRef.current = setTimeout(() => {
setShowReaction(false);
timeoutRef.current = null;
}, 3000);
}
// Clean up on unmount
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, [reactions, student.sub, visibleReactions]);
}, [reaction]);
return (
<Wrapper
@ -117,22 +104,19 @@ export const UserCard = ({
</AddMissedButton>
)}
{/* Student reactions animation */}
{/* Анимация реакции */}
<AnimatePresence>
{visibleReactions.map((reaction, index) => (
{showReaction && reaction && (
<motion.div
key={reaction._id || index}
initial={{ opacity: 0, scale: 0.5, x: 0, y: 0 }}
animate={{ opacity: 1, scale: 1, x: 0, y: 0 }}
key={reaction._id}
initial={{ opacity: 0, scale: 0.5, y: 0 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.5, y: -20 }}
transition={{
duration: 0.5,
delay: index * 0.1
}}
transition={{ duration: 0.5 }}
style={{
position: 'absolute',
top: '10px', // Position at the top
right: '10px', // Position at the right
top: '10px',
right: '10px',
zIndex: 10,
pointerEvents: 'none',
display: 'flex',
@ -146,17 +130,17 @@ export const UserCard = ({
title={t(`journal.pl.reactions.${reaction.reaction}`)}
>
<Text
fontSize="3xl" // Increased size
fontSize="3xl"
sx={{
filter: 'drop-shadow(0 1px 2px rgba(0,0,0,0.3))',
transform: 'scale(1.2)', // Additional scaling
transform: 'scale(1.2)',
display: 'flex'
}}
>
{REACTION_EMOJIS[reaction.reaction] || reaction.reaction}
</Text>
</motion.div>
))}
)}
</AnimatePresence>
</Wrapper>
)

View File

@ -382,7 +382,7 @@ const LessonDetail = () => {
present={student.present}
recentlyPresent={student.recentlyPresent}
onAddUser={(user: User) => manualAdd({ lessonId, user })}
reactions={studentReactions[student.sub] || []}
reaction={accessCode?.body?.lesson?.studentReactions?.find(r => r.sub === student.sub)}
/>
</Box>

View File

@ -277,7 +277,7 @@ const UserPage = () => {
student={student}
present={true}
recentlyPresent={student.isNew}
reactions={ls.data?.body?.studentReactions?.filter(r => r.sub === student.sub) || []}
reaction={ls.data?.body?.studentReactions?.find(r => r.sub === student.sub)}
/>
</motion.li>
))}