Spaces:
No application file
No application file
| import React, { useState, useEffect } from 'react'; | |
| interface CompactPetAvatarProps { | |
| health: number; | |
| energy: number; | |
| attention: number; | |
| } | |
| const CompactPetAvatar: React.FC<CompactPetAvatarProps> = ({ health, energy, attention }) => { | |
| const [isBlinking, setIsBlinking] = useState(false); | |
| const [mood, setMood] = useState<'happy' | 'normal' | 'tired' | 'sick'>('normal'); | |
| useEffect(() => { | |
| const blinkInterval = setInterval(() => { | |
| setIsBlinking(true); | |
| setTimeout(() => setIsBlinking(false), 150); | |
| }, 3000 + Math.random() * 2000); | |
| return () => clearInterval(blinkInterval); | |
| }, []); | |
| useEffect(() => { | |
| const avgStats = (health + energy + attention) / 3; | |
| if (avgStats >= 80) setMood('happy'); | |
| else if (avgStats >= 60) setMood('normal'); | |
| else if (avgStats >= 30) setMood('tired'); | |
| else setMood('sick'); | |
| }, [health, energy, attention]); | |
| const getMoodColor = () => { | |
| switch (mood) { | |
| case 'happy': return '#A7F3D0'; | |
| case 'normal': return '#BFDBFE'; | |
| case 'tired': return '#FDE68A'; | |
| case 'sick': return '#FECACA'; | |
| default: return '#BFDBFE'; | |
| } | |
| }; | |
| return ( | |
| <div className="flex items-center justify-center"> | |
| <div | |
| className="relative w-20 h-20 rounded-full animate-pulse transition-all duration-1000 shadow-lg" | |
| style={{ backgroundColor: getMoodColor() }} | |
| > | |
| {/* Pet body with gentle bounce animation */} | |
| <div className="absolute inset-1 rounded-full bg-white/20 animate-bounce" style={{ animationDuration: '3s' }}> | |
| {/* Eyes */} | |
| <div className="absolute top-4 left-2 flex space-x-3"> | |
| <div className={`w-3 h-3 bg-gray-800 rounded-full transition-all duration-150 ${isBlinking ? 'h-0.5' : 'h-3'}`}> | |
| {!isBlinking && <div className="w-1 h-1 bg-white rounded-full mt-0.5 ml-0.5"></div>} | |
| </div> | |
| <div className={`w-3 h-3 bg-gray-800 rounded-full transition-all duration-150 ${isBlinking ? 'h-0.5' : 'h-3'}`}> | |
| {!isBlinking && <div className="w-1 h-1 bg-white rounded-full mt-0.5 ml-0.5"></div>} | |
| </div> | |
| </div> | |
| {/* Mouth based on mood */} | |
| <div className="absolute top-11 left-1/2 transform -translate-x-1/2"> | |
| {mood === 'happy' && ( | |
| <div className="w-3 h-1.5 border-b-2 border-gray-800 rounded-full"></div> | |
| )} | |
| {mood === 'normal' && ( | |
| <div className="w-2 h-1 bg-gray-800 rounded-full"></div> | |
| )} | |
| {(mood === 'tired' || mood === 'sick') && ( | |
| <div className="w-3 h-1.5 border-t-2 border-gray-800 rounded-full"></div> | |
| )} | |
| </div> | |
| {/* Cheek blush for happy mood */} | |
| {mood === 'happy' && ( | |
| <> | |
| <div className="absolute top-6 left-1 w-2 h-2 bg-pink-300 rounded-full opacity-60"></div> | |
| <div className="absolute top-6 right-1 w-2 h-2 bg-pink-300 rounded-full opacity-60"></div> | |
| </> | |
| )} | |
| </div> | |
| {/* Floating particles for happy mood */} | |
| {mood === 'happy' && ( | |
| <div className="absolute -top-1 -right-1"> | |
| <div className="w-1 h-1 bg-yellow-300 rounded-full animate-ping"></div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default CompactPetAvatar; | |