Skip to content

Commit b3734af

Browse files
author
Ema
committed
Merge branch 'Catherine's-Branch--Warning-when-no-more-stars'
2 parents c395eb6 + c63899f commit b3734af

7 files changed

Lines changed: 269 additions & 166 deletions

File tree

src/components/OrbitSystem.tsx

Lines changed: 141 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { useState, useEffect } from 'react';
2+
import { useNavigate } from 'react-router';
3+
import { HeartCrack, Heart } from 'lucide-react';
24
import { mockAliens } from '../data/mockAliens';
35
import type { AlienProfile } from '../data/mockAliens';
46
import { useAppContext } from '../context/AppContext';
@@ -7,20 +9,23 @@ import { getCompatibility } from '../utils/compatibility';
79
import { useRocketNav } from '../context/TransitionContext';
810

911
export default function OrbitSystem() {
12+
const navigate = useNavigate();
1013
const { preferences, addMatch, matches } = useAppContext();
1114
const triggerRocketNav = useRocketNav();
1215
const [selectedAlien, setSelectedAlien] = useState<AlienProfile | null>(null);
1316
const [dismissedIds, setDismissedIds] = useState<Set<string>>(new Set());
14-
17+
const [showBreakingAnim, setShowBreakingAnim] = useState(false);
18+
const [animStage, setAnimStage] = useState<'none' | 'heart' | 'break' | 'final'>('none');
19+
1520
// Keep exactly 5 slots for the 5 orbit tracks
1621
const [activeIds, setActiveIds] = useState<(string | null)[]>([null, null, null, null, null]);
1722

1823
useEffect(() => {
1924
if (!preferences) return;
20-
25+
2126
// Available aliens are those within distance, not matched, not dismissed, and not currently active
22-
const available = mockAliens.filter(a =>
23-
a.distanceAU <= preferences.maxDistanceAU &&
27+
const available = mockAliens.filter(a =>
28+
a.distanceLY <= preferences.maxDistanceLY &&
2429
!matches.find(m => m.id === a.id) &&
2530
!dismissedIds.has(a.id) &&
2631
!activeIds.includes(a.id)
@@ -32,13 +37,13 @@ export default function OrbitSystem() {
3237

3338
let changed = false;
3439
const newActiveIds = [...activeIds];
35-
40+
3641
// Check each of the 5 tracks
3742
for (let i = 0; i < 5; i++) {
3843
const currentId = newActiveIds[i];
3944
// Check if the current alien in this track is still valid
40-
const isStillValid = currentId &&
41-
mockAliens.find(a => a.id === currentId && a.distanceAU <= preferences.maxDistanceAU) &&
45+
const isStillValid = currentId &&
46+
mockAliens.find(a => a.id === currentId && a.distanceLY <= preferences.maxDistanceLY) &&
4247
!matches.find(m => m.id === currentId) &&
4348
!dismissedIds.has(currentId);
4449

@@ -53,7 +58,16 @@ export default function OrbitSystem() {
5358
if (changed) {
5459
setActiveIds(newActiveIds);
5560
}
56-
}, [preferences, matches, dismissedIds, activeIds]);
61+
62+
// Trigger breaking animation if empty and not already shown
63+
if (newActiveIds.every(id => id === null) && animStage === 'none') {
64+
setAnimStage('heart');
65+
setTimeout(() => setAnimStage('break'), 1500);
66+
setTimeout(() => setAnimStage('final'), 2500);
67+
} else if (newActiveIds.some(id => id !== null)) {
68+
setAnimStage('none');
69+
}
70+
}, [preferences, matches, dismissedIds, activeIds, animStage]);
5771

5872
if (!preferences) return null;
5973

@@ -138,29 +152,48 @@ export default function OrbitSystem() {
138152
transform: scale(1.2);
139153
box-shadow: 0 0 25px var(--color-secondary);
140154
}
155+
@keyframes fadeIn {
156+
from { opacity: 0; transform: translateY(10px); }
157+
to { opacity: 1; transform: translateY(0); }
158+
}
159+
@keyframes heartPulse {
160+
0% { transform: scale(1); opacity: 0; }
161+
50% { transform: scale(1.1); opacity: 1; }
162+
100% { transform: scale(1); opacity: 1; }
163+
}
164+
@keyframes heartBreakLeft {
165+
0% { transform: translateX(0) rotate(0); }
166+
100% { transform: translateX(-50px) translateY(20px) rotate(-20deg); opacity: 0; }
167+
}
168+
@keyframes heartBreakRight {
169+
0% { transform: translateX(0) rotate(0); }
170+
100% { transform: translateX(50px) translateY(20px) rotate(20deg); opacity: 0; }
171+
}
141172
`}</style>
142173

143174
<div style={{ position: 'relative', width: '100%', flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }}>
144-
175+
145176
{/* User Center */}
146-
<div style={{
147-
width: '12vmin',
148-
height: '12vmin',
149-
minWidth: '60px',
150-
minHeight: '60px',
151-
borderRadius: '50%',
152-
background: 'linear-gradient(135deg, var(--color-primary), var(--color-secondary))',
153-
boxShadow: '0 0 30px var(--color-secondary)',
154-
display: 'flex',
155-
alignItems: 'center',
156-
justifyContent: 'center',
157-
fontWeight: 'bold',
158-
zIndex: 10,
159-
fontSize: 'clamp(1rem, 2.5vmin, 1.5rem)',
160-
color: 'white'
161-
}}>
162-
{preferences.name.substring(0, 2).toUpperCase() || 'YOU'}
163-
</div>
177+
{!activeIds.every(id => id === null) && (
178+
<div style={{
179+
width: '12vmin',
180+
height: '12vmin',
181+
minWidth: '60px',
182+
minHeight: '60px',
183+
borderRadius: '50%',
184+
background: 'linear-gradient(135deg, var(--color-primary), var(--color-secondary))',
185+
boxShadow: '0 0 30px var(--color-secondary)',
186+
display: 'flex',
187+
alignItems: 'center',
188+
justifyContent: 'center',
189+
fontWeight: 'bold',
190+
zIndex: 10,
191+
fontSize: 'clamp(1rem, 2.5vmin, 1.5rem)',
192+
color: 'white'
193+
}}>
194+
{preferences.name.substring(0, 2).toUpperCase() || 'YOU'}
195+
</div>
196+
)}
164197

165198
{/* Orbit Rings and Aliens */}
166199
{activeIds
@@ -171,19 +204,19 @@ export default function OrbitSystem() {
171204
.map((alien, i) => {
172205

173206
// Assign each slot to a distinct track (0 to 4)
174-
const rx = 120 + (i * 65);
175-
const ry = 80 + (i * 40);
176-
const duration = 15 + (i * 8);
177-
207+
const rx = 120 + (i * 65);
208+
const ry = 80 + (i * 40);
209+
const duration = 15 + (i * 8);
210+
178211
const delay = -1 * (i * (duration / 5));
179212

180213
return (
181214
<div key={`track-${i}-${alien.id}`}>
182215
{/* Ring */}
183216
<div className="orbit-ring" style={{ width: `${rx * 2}px`, height: `${ry * 2}px` }} />
184-
217+
185218
{/* Profile */}
186-
<div
219+
<div
187220
className="orbit-item"
188221
onClick={() => setSelectedAlien(alien)}
189222
style={{
@@ -194,20 +227,90 @@ export default function OrbitSystem() {
194227
'--duration': `${duration}s`,
195228
animationDelay: `${delay}s`
196229
}}
197-
title={`${alien.name} (${alien.distanceAU} AU)`}
230+
title={`${alien.name} (${alien.distanceLY} Light years)`}
198231
>
199232
<div className="orbit-avatar" style={{ backgroundImage: `url(${alien.profilePic})` }} />
200233
</div>
201234
</div>
202235
);
203236
})}
237+
238+
{/* Empty state message / Breaking Animation */}
239+
{animStage !== 'none' && (
240+
<div style={{
241+
position: 'absolute',
242+
zIndex: 100,
243+
display: 'flex',
244+
flexDirection: 'column',
245+
alignItems: 'center',
246+
justifyContent: 'center',
247+
textAlign: 'center',
248+
width: '100%',
249+
height: '100%',
250+
pointerEvents: animStage === 'final' ? 'auto' : 'none'
251+
}}>
252+
{(animStage === 'heart' || animStage === 'break') && (
253+
<div style={{ position: 'relative', width: '300px', height: '300px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
254+
<div style={{
255+
position: 'absolute',
256+
animation: animStage === 'break' ? 'heartBreakLeft 1.2s ease-in forwards' : 'heartPulse 1.5s ease-out infinite',
257+
}}>
258+
<Heart
259+
size={250}
260+
fill="var(--color-secondary)"
261+
color="var(--color-secondary)"
262+
style={{ clipPath: 'inset(0 50% 0 0)' }}
263+
/>
264+
</div>
265+
<div style={{
266+
position: 'absolute',
267+
animation: animStage === 'break' ? 'heartBreakRight 1.2s ease-in forwards' : 'heartPulse 1.5s ease-out infinite',
268+
}}>
269+
<Heart
270+
size={250}
271+
fill="var(--color-secondary)"
272+
color="var(--color-secondary)"
273+
style={{ clipPath: 'inset(0 0 0 50%)' }}
274+
/>
275+
</div>
276+
</div>
277+
)}
278+
279+
{animStage === 'final' && (
280+
<div className="glass-panel" style={{
281+
padding: '40px',
282+
maxWidth: '450px',
283+
animation: 'fadeIn 0.8s ease-out forwards',
284+
display: 'flex',
285+
flexDirection: 'column',
286+
alignItems: 'center',
287+
gap: '24px',
288+
pointerEvents: 'auto'
289+
}}>
290+
<p style={{ margin: 0, fontSize: '2.8rem', lineHeight: 1.1, color: 'var(--color-secondary)', fontWeight: 'bold' }}>
291+
The stars are not aligned
292+
</p>
293+
<p style={{ margin: 0, fontSize: '1.2rem', color: 'rgba(234, 222, 218, 0.8)', lineHeight: 1.4, marginTop: '8px' }}>
294+
Looks like you've run out of potential matches, check back later
295+
</p>
296+
<button
297+
onClick={() => { window.location.href = '/preferences'; }}
298+
className="btn-outline"
299+
style={{ marginTop: '8px', padding: '12px 40px', fontSize: '1rem', fontWeight: 'bold', cursor: 'pointer' }}
300+
>
301+
Back
302+
</button>
303+
</div>
304+
)}
305+
</div>
306+
)}
204307
</div>
205308

206309
{selectedAlien && (
207-
<ProfileModal
208-
alien={selectedAlien}
209-
onClose={() => setSelectedAlien(null)}
210-
onMatch={handleMatch}
310+
<ProfileModal
311+
alien={selectedAlien}
312+
onClose={() => setSelectedAlien(null)}
313+
onMatch={handleMatch}
211314
onDismiss={handleDismiss}
212315
/>
213316
)}

src/components/ProfileModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export default function ProfileModal({ alien, onClose, onMatch, onDismiss }: Pro
117117
<div>
118118
<h2 style={{ margin: 0, fontSize: '2rem', color: 'var(--color-secondary)' }}>{alien.name}, {alien.age}</h2>
119119
<p style={{ margin: '4px 0 0', color: 'rgba(234, 222, 218, 0.8)' }}>
120-
{alien.alienType}{alien.distanceAU} AU Away
120+
{alien.alienType}{alien.distanceLY} Light years Away
121121
</p>
122122
</div>
123123

src/context/AppContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export interface UserPreferences {
1212
limbs: number;
1313
alienType: string;
1414
size: string;
15-
maxDistanceAU: number;
15+
maxDistanceLY: number;
1616
goals: string;
1717
profilePic: string; // URL or base64
1818
}

0 commit comments

Comments
 (0)