Skip to content

Commit b92c73b

Browse files
committed
Add AnimatedWorkflow component for AI pipeline visualization
1 parent d016cbc commit b92c73b

2 files changed

Lines changed: 306 additions & 98 deletions

File tree

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
import { useState, useEffect } from 'react'
2+
import { Box, Typography, Paper } from '@mui/material'
3+
import { styled, keyframes } from '@mui/material/styles'
4+
import MusicNoteIcon from '@mui/icons-material/MusicNote'
5+
import SmartToyIcon from '@mui/icons-material/SmartToy'
6+
import CheckCircleIcon from '@mui/icons-material/CheckCircle'
7+
import AutoFixHighIcon from '@mui/icons-material/AutoFixHigh'
8+
import PianoIcon from '@mui/icons-material/Piano'
9+
10+
// Animation keyframes
11+
const pulse = keyframes`
12+
0%, 100% { transform: scale(1); opacity: 1; }
13+
50% { transform: scale(1.05); opacity: 0.8; }
14+
`
15+
16+
const flow = keyframes`
17+
0% { transform: translateX(-100%); }
18+
100% { transform: translateX(100%); }
19+
`
20+
21+
const glow = keyframes`
22+
0%, 100% { box-shadow: 0 0 5px #D35400, 0 0 10px #D35400; }
23+
50% { box-shadow: 0 0 20px #D35400, 0 0 30px #F1C40F; }
24+
`
25+
26+
const float = keyframes`
27+
0%, 100% { transform: translateY(0); }
28+
50% { transform: translateY(-10px); }
29+
`
30+
31+
const dataFlow = keyframes`
32+
0% { stroke-dashoffset: 100; }
33+
100% { stroke-dashoffset: 0; }
34+
`
35+
36+
const AnimatedBox = styled(Box)(({ theme, delay = 0 }) => ({
37+
animation: `${pulse} 2s ease-in-out ${delay}s infinite`,
38+
}))
39+
40+
const FlowingLine = styled(Box)({
41+
position: 'absolute',
42+
height: '4px',
43+
background: 'linear-gradient(90deg, transparent, #F1C40F, transparent)',
44+
animation: `${flow} 2s linear infinite`,
45+
})
46+
47+
const StepCard = styled(Paper)(({ theme, active }) => ({
48+
padding: '16px',
49+
textAlign: 'center',
50+
background: active
51+
? 'linear-gradient(135deg, #FFF8E1 0%, #FFECB3 100%)'
52+
: 'linear-gradient(135deg, #ffffff 0%, #f5f5f5 100%)',
53+
border: active ? '2px solid #D35400' : '1px solid #e0e0e0',
54+
borderRadius: '12px',
55+
transition: 'all 0.3s ease',
56+
animation: active ? `${glow} 2s ease-in-out infinite` : 'none',
57+
'&:hover': {
58+
transform: 'translateY(-5px)',
59+
boxShadow: '0 8px 25px rgba(211, 84, 0, 0.2)',
60+
},
61+
}))
62+
63+
const steps = [
64+
{
65+
icon: MusicNoteIcon,
66+
label: 'MIDI Input',
67+
description: 'Raw musical data',
68+
color: '#1976d2'
69+
},
70+
{
71+
icon: AutoFixHighIcon,
72+
label: 'Preprocessing',
73+
description: 'NoteSequences',
74+
color: '#388e3c'
75+
},
76+
{
77+
icon: SmartToyIcon,
78+
label: 'LSTM Training',
79+
description: 'Neural Network',
80+
color: '#d32f2f'
81+
},
82+
{
83+
icon: CheckCircleIcon,
84+
label: 'Validation',
85+
description: 'Raga Grammar',
86+
color: '#7b1fa2'
87+
},
88+
{
89+
icon: PianoIcon,
90+
label: 'Generation',
91+
description: 'Real-time Output',
92+
color: '#D35400'
93+
},
94+
]
95+
96+
function AnimatedWorkflow() {
97+
const [activeStep, setActiveStep] = useState(0)
98+
99+
useEffect(() => {
100+
const interval = setInterval(() => {
101+
setActiveStep((prev) => (prev + 1) % steps.length)
102+
}, 2000)
103+
return () => clearInterval(interval)
104+
}, [])
105+
106+
return (
107+
<Box sx={{ width: '100%', py: 3 }}>
108+
{/* Title */}
109+
<Typography
110+
variant="h6"
111+
sx={{
112+
textAlign: 'center',
113+
mb: 4,
114+
color: '#D35400',
115+
fontWeight: 600,
116+
animation: `${float} 3s ease-in-out infinite`,
117+
}}
118+
>
119+
🎵 DeepRaaga AI Pipeline in Action
120+
</Typography>
121+
122+
{/* Workflow Steps */}
123+
<Box
124+
sx={{
125+
display: 'flex',
126+
justifyContent: 'space-between',
127+
alignItems: 'center',
128+
gap: 2,
129+
flexWrap: 'wrap',
130+
position: 'relative',
131+
}}
132+
>
133+
{/* Connection Lines */}
134+
<svg
135+
style={{
136+
position: 'absolute',
137+
top: '50%',
138+
left: '10%',
139+
width: '80%',
140+
height: '4px',
141+
zIndex: 0,
142+
pointerEvents: 'none',
143+
}}
144+
>
145+
<defs>
146+
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="0%">
147+
<stop offset="0%" stopColor="#D35400" stopOpacity="0.3" />
148+
<stop offset="50%" stopColor="#F1C40F" stopOpacity="1" />
149+
<stop offset="100%" stopColor="#D35400" stopOpacity="0.3" />
150+
</linearGradient>
151+
</defs>
152+
<line
153+
x1="0"
154+
y1="2"
155+
x2="100%"
156+
y2="2"
157+
stroke="url(#lineGradient)"
158+
strokeWidth="4"
159+
strokeDasharray="10,5"
160+
style={{
161+
animation: `${dataFlow} 2s linear infinite`,
162+
}}
163+
/>
164+
</svg>
165+
166+
{steps.map((step, index) => {
167+
const Icon = step.icon
168+
const isActive = index === activeStep
169+
const isPast = index < activeStep
170+
171+
return (
172+
<AnimatedBox
173+
key={index}
174+
delay={index * 0.2}
175+
sx={{
176+
flex: '1 1 150px',
177+
maxWidth: '180px',
178+
zIndex: 1,
179+
}}
180+
>
181+
<StepCard active={isActive}>
182+
<Box sx={{
183+
display: 'flex',
184+
justifyContent: 'center',
185+
mb: 1,
186+
animation: isActive ? `${pulse} 1s ease-in-out infinite` : 'none',
187+
}}>
188+
<Icon
189+
sx={{
190+
fontSize: 40,
191+
color: isActive || isPast ? step.color : '#9e9e9e',
192+
transition: 'color 0.3s ease',
193+
}}
194+
/>
195+
</Box>
196+
<Typography
197+
variant="subtitle2"
198+
sx={{
199+
fontWeight: 'bold',
200+
color: isActive ? '#D35400' : (isPast ? '#333' : '#666'),
201+
mb: 0.5,
202+
}}
203+
>
204+
{step.label}
205+
</Typography>
206+
<Typography
207+
variant="caption"
208+
sx={{
209+
color: isActive ? '#666' : '#999',
210+
display: 'block',
211+
}}
212+
>
213+
{step.description}
214+
</Typography>
215+
{isActive && (
216+
<Box
217+
sx={{
218+
mt: 1,
219+
py: 0.5,
220+
px: 1,
221+
bgcolor: '#D35400',
222+
color: 'white',
223+
borderRadius: '12px',
224+
fontSize: '0.7rem',
225+
fontWeight: 'bold',
226+
display: 'inline-block',
227+
animation: `${pulse} 1s ease-in-out infinite`,
228+
}}
229+
>
230+
ACTIVE
231+
</Box>
232+
)}
233+
</StepCard>
234+
</AnimatedBox>
235+
)
236+
})}
237+
</Box>
238+
239+
{/* Status Bar */}
240+
<Box sx={{ mt: 4, textAlign: 'center' }}>
241+
<Paper
242+
elevation={2}
243+
sx={{
244+
display: 'inline-flex',
245+
alignItems: 'center',
246+
gap: 2,
247+
px: 3,
248+
py: 1.5,
249+
borderRadius: '25px',
250+
bgcolor: '#FFF8E1',
251+
border: '1px solid #F1C40F',
252+
}}
253+
>
254+
<Box
255+
sx={{
256+
width: 12,
257+
height: 12,
258+
borderRadius: '50%',
259+
bgcolor: '#4caf50',
260+
animation: `${pulse} 1s ease-in-out infinite`,
261+
}}
262+
/>
263+
<Typography variant="body2" sx={{ color: '#5D4037', fontWeight: 500 }}>
264+
Step {activeStep + 1} of {steps.length}: {steps[activeStep].label}
265+
</Typography>
266+
<Typography variant="caption" sx={{ color: '#8D6E63', ml: 1 }}>
267+
(Auto-cycling every 2 seconds)
268+
</Typography>
269+
</Paper>
270+
</Box>
271+
272+
{/* Data Flow Animation */}
273+
<Box sx={{ mt: 4, position: 'relative', height: '30px', overflow: 'hidden' }}>
274+
<Typography
275+
variant="caption"
276+
sx={{
277+
position: 'absolute',
278+
left: '50%',
279+
transform: 'translateX(-50%)',
280+
color: '#D35400',
281+
fontStyle: 'italic',
282+
animation: `${float} 2s ease-in-out infinite`,
283+
}}
284+
>
285+
◀ AI processing raga: Mayamalavagowla ▶
286+
</Typography>
287+
<Box
288+
sx={{
289+
position: 'absolute',
290+
bottom: 0,
291+
left: 0,
292+
right: 0,
293+
height: '3px',
294+
background: 'linear-gradient(90deg, transparent 0%, #D35400 50%, transparent 100%)',
295+
animation: `${flow} 3s linear infinite`,
296+
}}
297+
/>
298+
</Box>
299+
</Box>
300+
)
301+
}
302+
303+
export default AnimatedWorkflow

0 commit comments

Comments
 (0)