Skip to content

Commit c63899f

Browse files
Copilotemac129
andauthored
Merge origin/main and resolve PR conflicts
Agent-Logs-Url: https://github.com/devsuoa/devsuoa-devs-sesa-beginner-hackathon-2026-hot-encoded/sessions/c3164bed-425e-4ce9-a0e9-757ae0b61413 Co-authored-by: emac129 <174770429+emac129@users.noreply.github.com>
1 parent c2c168c commit c63899f

15 files changed

Lines changed: 704 additions & 96 deletions

.github/workflows/deploy.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ jobs:
2828

2929
- run: npm ci
3030
- run: npm run build
31+
env:
32+
VITE_GEMINI_API_KEY: ${{ secrets.VITE_GEMINI_API_KEY }}
3133

3234
- uses: actions/configure-pages@v5
3335

package-lock.json

Lines changed: 68 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"preview": "vite preview"
1111
},
1212
"dependencies": {
13+
"framer-motion": "^12.38.0",
1314
"lucide-react": "^1.8.0",
1415
"react": "^19.2.4",
1516
"react-dom": "^19.2.4",

src/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import Preferences from './pages/Preferences';
44
import Home from './pages/home/Home';
55
import Explore from './pages/Explore';
66
import Chat from './pages/Chat';
7+
import { RocketTransition } from './components/RocketTransition';
78

89
function App() {
910
const location = useLocation();
10-
const hideExploreLink = location.pathname === '/' || location.pathname === '/preferences';
1111
const isHomePage = location.pathname === '/';
1212

1313
return (
@@ -29,6 +29,8 @@ function App() {
2929
<Route path="/chat/:id" element={<Chat />} />
3030
</Routes>
3131
</main>
32+
33+
<RocketTransition />
3234
</div>
3335
);
3436
}

src/components/MatchOverlay.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import { useEffect } from 'react';
22
import type { AlienProfile } from '../data/mockAliens';
3-
import { useNavigate } from 'react-router';
43
import { Heart } from 'lucide-react';
4+
import { useRocketNav } from '../context/TransitionContext';
55

66
interface MatchOverlayProps {
77
alien: AlienProfile;
88
userName: string;
99
}
1010

1111
export default function MatchOverlay({ alien, userName }: MatchOverlayProps) {
12-
const navigate = useNavigate();
12+
const triggerRocketNav = useRocketNav();
1313

1414
useEffect(() => {
15-
// Automatically redirect to chat after 3 seconds
15+
// Trigger rocket navigation after 2 seconds (giving time to see the match)
1616
const timer = setTimeout(() => {
17-
navigate(`/chat/${alien.id}`);
18-
}, 3000);
17+
triggerRocketNav(`/chat/${alien.id}`);
18+
}, 2000);
1919
return () => clearTimeout(timer);
20-
}, [navigate, alien.id]);
20+
}, [triggerRocketNav, alien.id]);
2121

2222
return (
2323
<div style={{

src/components/OrbitSystem.tsx

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ import { mockAliens } from '../data/mockAliens';
55
import type { AlienProfile } from '../data/mockAliens';
66
import { useAppContext } from '../context/AppContext';
77
import ProfileModal from './ProfileModal';
8-
import MatchOverlay from './MatchOverlay';
8+
import { getCompatibility } from '../utils/compatibility';
9+
import { useRocketNav } from '../context/TransitionContext';
910

1011
export default function OrbitSystem() {
1112
const navigate = useNavigate();
1213
const { preferences, addMatch, matches } = useAppContext();
14+
const triggerRocketNav = useRocketNav();
1315
const [selectedAlien, setSelectedAlien] = useState<AlienProfile | null>(null);
14-
const [matchedAlien, setMatchedAlien] = useState<AlienProfile | null>(null);
1516
const [dismissedIds, setDismissedIds] = useState<Set<string>>(new Set());
1617
const [showBreakingAnim, setShowBreakingAnim] = useState(false);
1718
const [animStage, setAnimStage] = useState<'none' | 'heart' | 'break' | 'final'>('none');
@@ -30,6 +31,10 @@ export default function OrbitSystem() {
3031
!activeIds.includes(a.id)
3132
);
3233

34+
// Sort available aliens by compatibility descending, so the queue is ordered
35+
// from highest match to lowest match. The next alien pulled will always be the highest remaining match.
36+
available.sort((a, b) => getCompatibility(b, preferences) - getCompatibility(a, preferences));
37+
3338
let changed = false;
3439
const newActiveIds = [...activeIds];
3540

@@ -69,7 +74,7 @@ export default function OrbitSystem() {
6974
const handleMatch = (alien: AlienProfile) => {
7075
addMatch(alien);
7176
setSelectedAlien(null);
72-
setMatchedAlien(alien);
77+
triggerRocketNav(`/chat/${alien.id}`, { alienImg: alien.profilePic });
7378
};
7479

7580
const handleDismiss = (alien: AlienProfile) => {
@@ -78,10 +83,28 @@ export default function OrbitSystem() {
7883
newSet.add(alien.id);
7984
return newSet;
8085
});
81-
setSelectedAlien(null);
86+
87+
// Find the next available alien in activeIds
88+
const currentIndex = activeIds.indexOf(alien.id);
89+
let nextId = null;
90+
if (currentIndex >= 0) {
91+
for(let i=1; i<5; i++) {
92+
const candidate = activeIds[(currentIndex + i) % 5];
93+
if (candidate && candidate !== alien.id) {
94+
nextId = candidate;
95+
break;
96+
}
97+
}
98+
}
99+
100+
if (nextId) {
101+
const nextAlien = mockAliens.find(a => a.id === nextId);
102+
setSelectedAlien(nextAlien || null);
103+
} else {
104+
setSelectedAlien(null);
105+
}
82106
};
83107

84-
const visibleAliens = mockAliens.filter(a => activeIds.includes(a.id));
85108

86109
return (
87110
<>
@@ -173,11 +196,12 @@ export default function OrbitSystem() {
173196
)}
174197

175198
{/* Orbit Rings and Aliens */}
176-
{activeIds.map((id, i) => {
177-
if (!id) return null; // If no alien is available for this slot, don't render it
178-
179-
const alien = mockAliens.find(a => a.id === id);
180-
if (!alien) return null;
199+
{activeIds
200+
.map(id => id ? mockAliens.find(a => a.id === id) : null)
201+
.filter((a): a is AlienProfile => a !== null && a !== undefined)
202+
// Sort by compatibility descending so the highest match is in the innermost track
203+
.sort((a, b) => getCompatibility(b, preferences) - getCompatibility(a, preferences))
204+
.map((alien, i) => {
181205

182206
// Assign each slot to a distinct track (0 to 4)
183207
const rx = 120 + (i * 65);
@@ -291,12 +315,6 @@ export default function OrbitSystem() {
291315
/>
292316
)}
293317

294-
{matchedAlien && (
295-
<MatchOverlay
296-
alien={matchedAlien}
297-
userName={preferences.name || 'User'}
298-
/>
299-
)}
300318
</>
301319
);
302320
}

0 commit comments

Comments
 (0)