This commit is contained in:
2025-11-26 17:03:29 +01:00
parent ff3528e5ef
commit fef75008d8
147 changed files with 112370 additions and 5162 deletions

View File

@@ -2,6 +2,9 @@ import React, { useState, useEffect, useCallback } from 'react';
import { SessionCreationForm } from './components/SessionCreationForm';
import { SessionProgressMonitor } from './components/SessionProgressMonitor';
import { LoginPrompt } from './components/LoginPrompt';
import { BrowserModeToggle } from './components/BrowserModeToggle';
import { CheckoutConfirmationDialog } from './components/CheckoutConfirmationDialog';
import { RaceCreationSuccessScreen } from './components/RaceCreationSuccessScreen';
import type { HostedSessionConfig } from '../../../packages/domain/entities/HostedSessionConfig';
interface SessionProgress {
@@ -24,6 +27,26 @@ export function App() {
const [isRunning, setIsRunning] = useState(false);
const [loginStatus, setLoginStatus] = useState<LoginStatus>('idle');
const [checkoutRequest, setCheckoutRequest] = useState<{
price: string;
state: 'ready' | 'insufficient_funds';
sessionMetadata: {
sessionName: string;
trackId: string;
carIds: string[];
};
timeoutMs: number;
} | null>(null);
const [raceCreationResult, setRaceCreationResult] = useState<{
sessionId: string;
sessionName: string;
trackId: string;
carIds: string[];
finalPrice: string;
createdAt: Date;
} | null>(null);
const handleLogin = useCallback(async () => {
if (!window.electronAPI) return;
@@ -91,6 +114,11 @@ export function App() {
}
};
// Subscribe to checkout confirmation requests
const unsubscribeCheckout = window.electronAPI.onCheckoutConfirmationRequest((request) => {
setCheckoutRequest(request);
});
checkAuth();
window.electronAPI.onSessionProgress((newProgress: SessionProgress) => {
@@ -101,6 +129,11 @@ export function App() {
setIsRunning(false);
}
});
// Cleanup subscription on unmount
return () => {
unsubscribeCheckout?.();
};
}, []);
const handleStartAutomation = async (config: HostedSessionConfig) => {
@@ -157,6 +190,16 @@ export function App() {
);
}
// Show checkout confirmation dialog if requested
if (checkoutRequest) {
return <CheckoutConfirmationDialog request={checkoutRequest} />;
}
// Show race creation success screen if completed
if (raceCreationResult) {
return <RaceCreationSuccessScreen result={raceCreationResult} />;
}
if (authState !== 'AUTHENTICATED') {
return (
<LoginPrompt
@@ -178,37 +221,42 @@ export function App() {
<div style={{
flex: 1,
padding: '2rem',
borderRight: '1px solid #333'
borderRight: '1px solid #333',
display: 'flex',
flexDirection: 'column'
}}>
<h1 style={{ marginBottom: '2rem', color: '#fff' }}>
GridPilot Companion
</h1>
<p style={{ marginBottom: '2rem', color: '#aaa' }}>
Hosted Session Automation POC
</p>
<div style={{ flex: 1 }}>
<h1 style={{ marginBottom: '2rem', color: '#fff' }}>
GridPilot Companion
</h1>
<p style={{ marginBottom: '2rem', color: '#aaa' }}>
Hosted Session Automation POC
</p>
<SessionCreationForm
onSubmit={handleStartAutomation}
disabled={isRunning}
/>
{isRunning && (
<button
onClick={handleStopAutomation}
style={{
marginTop: '1rem',
padding: '0.75rem 1.5rem',
backgroundColor: '#dc3545',
color: '#fff',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1rem',
fontWeight: 'bold'
}}
>
Stop Automation
</button>
)}
<SessionCreationForm
onSubmit={handleStartAutomation}
disabled={isRunning}
/>
{isRunning && (
<button
onClick={handleStopAutomation}
style={{
marginTop: '1rem',
padding: '0.75rem 1.5rem',
backgroundColor: '#dc3545',
color: '#fff',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1rem',
fontWeight: 'bold'
}}
>
Stop Automation
</button>
)}
</div>
<BrowserModeToggle />
</div>
<div style={{
flex: 1,