Skip to content

Commit baeca24

Browse files
committed
Merge branch 'apollo3'
# Conflicts: # src/components/OrbitSystem.tsx
2 parents 6f251d9 + 2efc0af commit baeca24

7 files changed

Lines changed: 671 additions & 31 deletions

File tree

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Home from './pages/home/Home';
55
import Explore from './pages/Explore';
66
import Chat from './pages/Chat';
77
import { RocketTransition } from './components/RocketTransition';
8+
import UserProfileWidget from './components/UserProfileWidget';
89

910
function App() {
1011
const location = useLocation();
@@ -19,6 +20,7 @@ function App() {
1920
</Link>
2021
</div>
2122
)}
23+
{!isHomePage && <UserProfileWidget />}
2224

2325
<main className="main-content">
2426
<Routes>

src/components/OrbitSystem.tsx

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@ import { useAppContext } from '../context/AppContext';
66
import ProfileModal from './ProfileModal';
77
import { getCompatibility } from '../utils/compatibility';
88
import { useRocketNav } from '../context/TransitionContext';
9+
import ScientificWarningModal from './ScientificWarningModal';
10+
import { getScientificWarnings } from '../utils/scienceWarnings';
911

1012
export default function OrbitSystem() {
1113

1214
const { preferences, addMatch, matches } = useAppContext();
1315
const triggerRocketNav = useRocketNav();
1416
const [selectedAlien, setSelectedAlien] = useState<AlienProfile | null>(null);
1517
const [dismissedIds, setDismissedIds] = useState<Set<string>>(new Set());
16-
1718
const [animStage, setAnimStage] = useState<'none' | 'heart' | 'break' | 'final'>('none');
18-
19+
const [pendingMatchAlien, setPendingMatchAlien] = useState<AlienProfile | null>(null);
20+
1921
// Keep exactly 5 slots for the 5 orbit tracks
2022
const [activeIds, setActiveIds] = useState<(string | null)[]>([null, null, null, null, null]);
2123

@@ -71,8 +73,22 @@ export default function OrbitSystem() {
7173
if (!preferences) return null;
7274

7375
const handleMatch = (alien: AlienProfile) => {
76+
const warnings = getScientificWarnings(alien);
77+
if (warnings.length > 0) {
78+
// Hazards detected — close modal and show warning first
79+
setSelectedAlien(null);
80+
setPendingMatchAlien(alien);
81+
} else {
82+
// No hazards — proceed directly
83+
addMatch(alien);
84+
setSelectedAlien(null);
85+
triggerRocketNav(`/chat/${alien.id}`, { alienImg: alien.profilePic });
86+
}
87+
};
88+
89+
const confirmMatch = (alien: AlienProfile) => {
7490
addMatch(alien);
75-
setSelectedAlien(null);
91+
setPendingMatchAlien(null);
7692
triggerRocketNav(`/chat/${alien.id}`, { alienImg: alien.profilePic });
7793
};
7894

@@ -108,10 +124,26 @@ export default function OrbitSystem() {
108124
return (
109125
<>
110126
<style>{`
111-
@keyframes orbit {
127+
@keyframes orbit-0 {
112128
from { offset-distance: 0%; }
113129
to { offset-distance: 100%; }
114130
}
131+
@keyframes orbit-1 {
132+
from { offset-distance: 20%; }
133+
to { offset-distance: 120%; }
134+
}
135+
@keyframes orbit-2 {
136+
from { offset-distance: 40%; }
137+
to { offset-distance: 140%; }
138+
}
139+
@keyframes orbit-3 {
140+
from { offset-distance: 60%; }
141+
to { offset-distance: 160%; }
142+
}
143+
@keyframes orbit-4 {
144+
from { offset-distance: 80%; }
145+
to { offset-distance: 180%; }
146+
}
115147
.orbit-ring {
116148
position: absolute;
117149
top: 50%;
@@ -131,7 +163,9 @@ export default function OrbitSystem() {
131163
cursor: pointer;
132164
offset-path: ellipse(var(--rx) var(--ry) at 50% 50%);
133165
offset-rotate: 0deg;
134-
animation: orbit var(--duration) linear infinite;
166+
animation-duration: var(--duration);
167+
animation-timing-function: linear;
168+
animation-iteration-count: infinite;
135169
}
136170
.orbit-avatar {
137171
width: 100%;
@@ -173,26 +207,27 @@ export default function OrbitSystem() {
173207
<div style={{ position: 'relative', width: '100%', flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }}>
174208

175209
{/* User Center */}
176-
{!activeIds.every(id => id === null) && (
177-
<div style={{
178-
width: '12vmin',
179-
height: '12vmin',
180-
minWidth: '60px',
181-
minHeight: '60px',
182-
borderRadius: '50%',
183-
background: 'linear-gradient(135deg, var(--color-primary), var(--color-secondary))',
184-
boxShadow: '0 0 30px var(--color-secondary)',
185-
display: 'flex',
186-
alignItems: 'center',
187-
justifyContent: 'center',
188-
fontWeight: 'bold',
189-
zIndex: 10,
190-
fontSize: 'clamp(1rem, 2.5vmin, 1.5rem)',
191-
color: 'white'
192-
}}>
193-
{preferences.name.substring(0, 2).toUpperCase() || 'YOU'}
194-
</div>
195-
)}
210+
<div style={{
211+
width: '12vmin',
212+
height: '12vmin',
213+
minWidth: '60px',
214+
minHeight: '60px',
215+
borderRadius: '50%',
216+
background: preferences.profilePic
217+
? `url(${preferences.profilePic}) center/cover`
218+
: 'linear-gradient(135deg, var(--color-primary), var(--color-secondary))',
219+
boxShadow: '0 0 30px var(--color-secondary)',
220+
display: 'flex',
221+
alignItems: 'center',
222+
justifyContent: 'center',
223+
fontWeight: 'bold',
224+
zIndex: 10,
225+
fontSize: 'clamp(1rem, 2.5vmin, 1.5rem)',
226+
color: 'white',
227+
border: '2px solid var(--color-secondary)',
228+
}}>
229+
{!preferences.profilePic && (preferences.name.substring(0, 2).toUpperCase() || 'YOU')}
230+
</div>
196231

197232
{/* Orbit Rings and Aliens */}
198233
{activeIds
@@ -224,7 +259,7 @@ export default function OrbitSystem() {
224259
'--rx': `${rx}px`,
225260
'--ry': `${ry}px`,
226261
'--duration': `${duration}s`,
227-
animationDelay: `${delay}s`
262+
animationName: `orbit-${i}`
228263
}}
229264
title={`${alien.name} (${alien.distanceLY} Light years)`}
230265
>
@@ -314,6 +349,14 @@ export default function OrbitSystem() {
314349
/>
315350
)}
316351

352+
{pendingMatchAlien && (
353+
<ScientificWarningModal
354+
alien={pendingMatchAlien}
355+
onProceed={() => confirmMatch(pendingMatchAlien)}
356+
onCancel={() => setPendingMatchAlien(null)}
357+
/>
358+
)}
359+
317360
</>
318361
);
319362
}

src/components/ProfileModal.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { useState, useEffect } from 'react';
22
import type { AlienProfile } from '../data/mockAliens';
3-
import { X, Heart, Info, Globe, Wind } from 'lucide-react';
3+
import { X, Heart, Info, Globe, Wind, Thermometer } from 'lucide-react';
44
import { useAppContext } from '../context/AppContext';
55
import { getCompatibility } from '../utils/compatibility';
6+
import { getScientificWarnings } from '../utils/scienceWarnings';
67

78
interface ProfileModalProps {
89
alien: AlienProfile;
@@ -15,6 +16,16 @@ export default function ProfileModal({ alien, onClose, onMatch, onDismiss }: Pro
1516
const [swipeDirection, setSwipeDirection] = useState<'left' | 'right' | null>(null);
1617
const { preferences } = useAppContext();
1718
const compatibility = getCompatibility(alien, preferences);
19+
const warnings = getScientificWarnings(alien);
20+
const warnedLabels = new Set(warnings.map(w => w.label.toLowerCase()));
21+
22+
// Helper: return red/orange border colour if a stat is flagged
23+
const dangerFor = (key: string) => {
24+
const w = warnings.find(w => w.label.toLowerCase().includes(key.toLowerCase()));
25+
if (!w) return 'rgba(234, 222, 218, 0.1)';
26+
return w.severity === 'danger' ? 'rgba(220, 38, 38, 0.6)' : 'rgba(245, 158, 11, 0.6)';
27+
};
28+
void warnedLabels;
1829

1930
useEffect(() => {
2031
setSwipeDirection(null);
@@ -156,17 +167,23 @@ export default function ProfileModal({ alien, onClose, onMatch, onDismiss }: Pro
156167
</h3>
157168

158169
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginTop: '16px', marginBottom: '32px' }}>
159-
<div className="glass-panel" style={{ padding: '16px', textAlign: 'center', border: '1px solid rgba(234, 222, 218, 0.1)' }}>
170+
<div className="glass-panel" style={{ padding: '16px', textAlign: 'center', border: `1px solid ${dangerFor('gravity')}` }}>
160171
<div style={{ fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--color-primary)' }}>{alien.gravityGs}G</div>
161172
<div style={{ fontSize: '0.8rem', opacity: 0.8 }}>Gravity</div>
162173
</div>
163-
<div className="glass-panel" style={{ padding: '16px', textAlign: 'center', border: '1px solid rgba(234, 222, 218, 0.1)' }}>
174+
<div className="glass-panel" style={{ padding: '16px', textAlign: 'center', border: `1px solid ${dangerFor('oxygen')}` }}>
164175
<div style={{ fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--color-primary)' }}>{alien.oxygenPercent}%</div>
165176
<div style={{ fontSize: '0.8rem', opacity: 0.8 }}>Atmospheric Oxygen</div>
166177
</div>
167-
<div className="glass-panel" style={{ gridColumn: 'span 2', padding: '16px', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px', border: '1px solid rgba(234, 222, 218, 0.1)' }}>
178+
<div className="glass-panel" style={{ padding: '16px', textAlign: 'center', border: `1px solid ${dangerFor('temperature') || dangerFor('heat') || dangerFor('cold')}` }}>
179+
<div style={{ fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--color-primary)', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '6px' }}>
180+
<Thermometer size={20} />{alien.homeTemperatureC.toLocaleString()}°C
181+
</div>
182+
<div style={{ fontSize: '0.8rem', opacity: 0.8 }}>Surface Temperature</div>
183+
</div>
184+
<div className="glass-panel" style={{ padding: '16px', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px', border: `1px solid ${dangerFor('surface') || dangerFor('ocean')}` }}>
168185
{alien.planetType === 'Gas Giant' ? <Wind size={20} /> : <Globe size={20} />}
169-
<span style={{ fontWeight: 'bold' }}>{alien.planetType}</span>
186+
<span style={{ fontWeight: 'bold', fontSize: '0.9rem' }}>{alien.planetType}</span>
170187
</div>
171188
</div>
172189

0 commit comments

Comments
 (0)