Skip to content

Commit 93ee7f5

Browse files
committed
Add avatar generation test page
- Create /avatar-test page to test philosophy colors and work style animations - Generate 4 random avatars with different philosophy and work style combinations - Add regenerate button to create new random combinations - Include legend showing all philosophy colors and work style animations - Test the complete avatar generation system with random data - Each avatar shows: name, role, description, philosophy, work style, and keywords - Animated avatars demonstrate color and animation combinations - Responsive grid layout for avatar cards - Sticky header with regenerate functionality
1 parent 9f33d81 commit 93ee7f5

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed

src/app/avatar-test/page.tsx

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
'use client';
2+
3+
import { useState, useEffect } from 'react';
4+
import { motion } from 'framer-motion';
5+
import { RefreshCw, Sparkles } from 'lucide-react';
6+
import Avatar from '@/components/Avatar';
7+
8+
interface TestAvatar {
9+
id: number;
10+
name: string;
11+
philosophy: string;
12+
workingStyle: string;
13+
role: string;
14+
description: string;
15+
keywords: string[];
16+
}
17+
18+
const PHILOSOPHIES = ['rewarded', 'playful', 'scalable', 'one-team', 'clarity', 'grit'];
19+
const WORKING_STYLES = ['iterative', 'detail-oriented', 'big-picture', 'collaborative', 'experimental', 'systematic'];
20+
const NAMES = ['Alex Chen', 'Maya Patel', 'Jordan Kim', 'Sam Wilson', 'Taylor Brown', 'Casey Lee', 'Riley Zhang', 'Morgan Davis'];
21+
const ROLES = ['Product Designer', 'UX Designer', 'UI Designer', 'Design Lead', 'Design Manager'];
22+
const DESCRIPTIONS = [
23+
'Creating user-centered experiences that drive engagement',
24+
'Building intuitive interfaces that users love',
25+
'Leading design strategy and vision for product teams',
26+
'Crafting beautiful and functional digital products',
27+
'Designing systems that scale with business growth'
28+
];
29+
const KEYWORDS = [
30+
['User Research', 'Prototyping', 'Design Systems'],
31+
['Visual Design', 'Branding', 'Illustration'],
32+
['Strategy', 'Leadership', 'Cross-functional'],
33+
['Accessibility', 'Usability', 'Information Architecture'],
34+
['Motion Design', 'Interaction Design', 'Frontend'],
35+
['Data Visualization', 'Analytics', 'Growth Design']
36+
];
37+
38+
function generateRandomAvatar(id: number): TestAvatar {
39+
const randomName = NAMES[Math.floor(Math.random() * NAMES.length)];
40+
const randomPhilosophy = PHILOSOPHIES[Math.floor(Math.random() * PHILOSOPHIES.length)];
41+
const randomWorkingStyle = WORKING_STYLES[Math.floor(Math.random() * WORKING_STYLES.length)];
42+
const randomRole = ROLES[Math.floor(Math.random() * ROLES.length)];
43+
const randomDescription = DESCRIPTIONS[Math.floor(Math.random() * DESCRIPTIONS.length)];
44+
const randomKeywords = KEYWORDS[Math.floor(Math.random() * KEYWORDS.length)];
45+
46+
return {
47+
id,
48+
name: randomName,
49+
philosophy: randomPhilosophy,
50+
workingStyle: randomWorkingStyle,
51+
role: randomRole,
52+
description: randomDescription,
53+
keywords: randomKeywords,
54+
};
55+
}
56+
57+
export default function AvatarTestPage() {
58+
const [avatars, setAvatars] = useState<TestAvatar[]>([]);
59+
const [isGenerating, setIsGenerating] = useState(false);
60+
61+
const generateAvatars = () => {
62+
setIsGenerating(true);
63+
64+
// Generate 4 random avatars
65+
const newAvatars = Array.from({ length: 4 }, (_, index) =>
66+
generateRandomAvatar(index + 1)
67+
);
68+
69+
setAvatars(newAvatars);
70+
71+
// Reset generating state after animation
72+
setTimeout(() => setIsGenerating(false), 500);
73+
};
74+
75+
useEffect(() => {
76+
// Generate initial avatars on page load
77+
generateAvatars();
78+
}, []);
79+
80+
return (
81+
<div className="min-h-screen bg-background">
82+
{/* Header */}
83+
<div className="border-b border-border bg-background/80 backdrop-blur-sm sticky top-0 z-10">
84+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
85+
<div className="flex items-center justify-between">
86+
<div>
87+
<h1 className="text-3xl font-bold text-foreground">Avatar Generation Test</h1>
88+
<p className="text-muted-foreground mt-2">
89+
Testing philosophy-based colors and work style animations
90+
</p>
91+
</div>
92+
93+
<motion.button
94+
whileHover={{ scale: 1.02 }}
95+
whileTap={{ scale: 0.98 }}
96+
onClick={generateAvatars}
97+
disabled={isGenerating}
98+
className={`flex items-center space-x-2 px-6 py-3 rounded-lg font-medium transition-colors ${
99+
isGenerating
100+
? 'text-muted-foreground cursor-not-allowed'
101+
: 'bg-accent text-white hover:bg-accent/90'
102+
}`}
103+
>
104+
<motion.div
105+
animate={isGenerating ? { rotate: 360 } : { rotate: 0 }}
106+
transition={{ duration: 0.5, repeat: isGenerating ? Infinity : 0 }}
107+
>
108+
<RefreshCw className="w-4 h-4" />
109+
</motion.div>
110+
<span>{isGenerating ? 'Generating...' : 'Regenerate'}</span>
111+
</motion.button>
112+
</div>
113+
</div>
114+
</div>
115+
116+
{/* Content */}
117+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
118+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
119+
{avatars.map((avatar, index) => (
120+
<motion.div
121+
key={avatar.id}
122+
initial={{ opacity: 0, y: 20 }}
123+
animate={{ opacity: 1, y: 0 }}
124+
transition={{ delay: index * 0.1, duration: 0.5 }}
125+
className="bg-gradient-to-br from-background to-muted/20 p-6 rounded-2xl border border-border shadow-lg hover:shadow-xl transition-shadow"
126+
>
127+
{/* Avatar */}
128+
<div className="flex justify-center mb-6">
129+
<Avatar
130+
name={avatar.name}
131+
size={80}
132+
philosophy={avatar.philosophy}
133+
workingStyle={avatar.workingStyle}
134+
/>
135+
</div>
136+
137+
{/* Info */}
138+
<div className="space-y-4">
139+
<div>
140+
<h3 className="text-lg font-semibold text-foreground mb-1">{avatar.name}</h3>
141+
<p className="text-muted-foreground text-sm mb-2">{avatar.role}</p>
142+
<p className="text-muted-foreground text-xs">{avatar.description}</p>
143+
</div>
144+
145+
{/* Philosophy & Work Style */}
146+
<div className="space-y-2">
147+
<div className="flex items-center justify-between">
148+
<span className="text-xs text-muted-foreground">Philosophy:</span>
149+
<span className="text-xs font-medium text-accent capitalize px-2 py-1 bg-accent/10 rounded-full">
150+
{avatar.philosophy}
151+
</span>
152+
</div>
153+
<div className="flex items-center justify-between">
154+
<span className="text-xs text-muted-foreground">Work Style:</span>
155+
<span className="text-xs font-medium text-accent capitalize px-2 py-1 bg-accent/10 rounded-full">
156+
{avatar.workingStyle.replace('-', ' ')}
157+
</span>
158+
</div>
159+
</div>
160+
161+
{/* Keywords */}
162+
<div>
163+
<h4 className="text-xs font-medium text-foreground mb-2">Expertise</h4>
164+
<div className="flex flex-wrap gap-1">
165+
{avatar.keywords.map((keyword, keywordIndex) => (
166+
<span
167+
key={keywordIndex}
168+
className="px-2 py-1 bg-accent/10 text-accent rounded-full text-xs font-medium"
169+
>
170+
{keyword}
171+
</span>
172+
))}
173+
</div>
174+
</div>
175+
</div>
176+
</motion.div>
177+
))}
178+
</div>
179+
180+
{/* Legend */}
181+
<div className="mt-16 p-8 bg-muted/20 rounded-2xl border border-border">
182+
<h2 className="text-2xl font-bold text-foreground mb-6 flex items-center">
183+
<Sparkles className="w-6 h-6 mr-2 text-accent" />
184+
Generation System
185+
</h2>
186+
187+
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
188+
{/* Philosophy Colors */}
189+
<div>
190+
<h3 className="text-lg font-semibold text-foreground mb-4">Philosophy-Based Colors</h3>
191+
<div className="space-y-3">
192+
{PHILOSOPHIES.map((philosophy) => (
193+
<div key={philosophy} className="flex items-center space-x-3">
194+
<div className="w-6 h-6 rounded-full border-2 border-border flex items-center justify-center">
195+
<Avatar
196+
name="Test"
197+
size={20}
198+
philosophy={philosophy}
199+
workingStyle="systematic"
200+
/>
201+
</div>
202+
<span className="text-sm text-foreground capitalize">{philosophy}</span>
203+
</div>
204+
))}
205+
</div>
206+
</div>
207+
208+
{/* Work Style Animations */}
209+
<div>
210+
<h3 className="text-lg font-semibold text-foreground mb-4">Work Style Animations</h3>
211+
<div className="space-y-3">
212+
{WORKING_STYLES.map((style) => (
213+
<div key={style} className="flex items-center space-x-3">
214+
<div className="w-6 h-6 rounded-full border-2 border-border flex items-center justify-center">
215+
<Avatar
216+
name="Test"
217+
size={20}
218+
philosophy="playful"
219+
workingStyle={style}
220+
/>
221+
</div>
222+
<span className="text-sm text-foreground capitalize">{style.replace('-', ' ')}</span>
223+
</div>
224+
))}
225+
</div>
226+
</div>
227+
</div>
228+
</div>
229+
</div>
230+
</div>
231+
);
232+
}

0 commit comments

Comments
 (0)