Упрощено управление реакциями студентов в карточке пользователя. Изменено состояние реакций на использование одного объекта вместо массива, улучшена анимация отображения реакций.
This commit is contained in:
parent
56a04dbe14
commit
d648a181c3
@ -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>
|
||||
)
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
))}
|
||||
|
Loading…
x
Reference in New Issue
Block a user