/**
* @ai-summary Main app component with routing and mobile navigation
*/
import { useState, useEffect, useTransition, useCallback, lazy } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { Routes, Route, Navigate } from 'react-router-dom';
import { useAuth0 } from '@auth0/auth0-react';
import { motion, AnimatePresence } from 'framer-motion';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
import DirectionsCarRoundedIcon from '@mui/icons-material/DirectionsCarRounded';
import LocalGasStationRoundedIcon from '@mui/icons-material/LocalGasStationRounded';
import SettingsRoundedIcon from '@mui/icons-material/SettingsRounded';
import { md3Theme } from './shared-minimal/theme/md3Theme';
import { Layout } from './components/Layout';
import { UnitsProvider } from './core/units/UnitsContext';
// Lazy load route components for better initial bundle size
const VehiclesPage = lazy(() => import('./features/vehicles/pages/VehiclesPage').then(m => ({ default: m.VehiclesPage })));
const VehicleDetailPage = lazy(() => import('./features/vehicles/pages/VehicleDetailPage').then(m => ({ default: m.VehicleDetailPage })));
const SettingsPage = lazy(() => import('./pages/SettingsPage').then(m => ({ default: m.SettingsPage })));
const FuelLogsPage = lazy(() => import('./features/fuel-logs/pages/FuelLogsPage').then(m => ({ default: m.FuelLogsPage })));
const VehiclesMobileScreen = lazy(() => import('./features/vehicles/mobile/VehiclesMobileScreen').then(m => ({ default: m.VehiclesMobileScreen })));
const VehicleDetailMobile = lazy(() => import('./features/vehicles/mobile/VehicleDetailMobile').then(m => ({ default: m.VehicleDetailMobile })));
import { BottomNavigation, NavigationItem } from './shared-minimal/components/mobile/BottomNavigation';
import { GlassCard } from './shared-minimal/components/mobile/GlassCard';
import { Button } from './shared-minimal/components/Button';
import { RouteSuspense } from './components/SuspenseWrappers';
import { Vehicle } from './features/vehicles/types/vehicles.types';
import { FuelLogForm } from './features/fuel-logs/components/FuelLogForm';
import { FuelLogsList } from './features/fuel-logs/components/FuelLogsList';
import { FuelLogEditDialog } from './features/fuel-logs/components/FuelLogEditDialog';
import { useFuelLogs } from './features/fuel-logs/hooks/useFuelLogs';
import { FuelLogResponse, UpdateFuelLogRequest } from './features/fuel-logs/types/fuel-logs.types';
import { fuelLogsApi } from './features/fuel-logs/api/fuel-logs.api';
import { VehicleForm } from './features/vehicles/components/VehicleForm';
import { useOptimisticVehicles } from './features/vehicles/hooks/useOptimisticVehicles';
import { CreateVehicleRequest } from './features/vehicles/types/vehicles.types';
import { MobileSettingsScreen } from './features/settings/mobile/MobileSettingsScreen';
import { useNavigationStore, useUserStore } from './core/store';
import { useDataSync } from './core/hooks/useDataSync';
import { MobileDebugPanel } from './core/debug/MobileDebugPanel';
import { MobileErrorBoundary } from './core/error-boundaries/MobileErrorBoundary';
// Hoisted mobile screen components to stabilize identity and prevent remounts
const DashboardScreen: React.FC = () => (
Dashboard
Coming soon - Vehicle insights and analytics
);
const LogFuelScreen: React.FC = () => {
const queryClient = useQueryClient();
const [editingLog, setEditingLog] = useState(null);
const { goBack, canGoBack, navigateToScreen } = useNavigationStore();
useEffect(() => {
console.log('[LogFuelScreen] Mounted');
return () => console.log('[LogFuelScreen] Unmounted');
}, []);
let fuelLogs: FuelLogResponse[] | undefined, isLoading: boolean | undefined, error: any;
try {
const hookResult = useFuelLogs();
fuelLogs = hookResult.fuelLogs;
isLoading = hookResult.isLoading;
error = hookResult.error;
} catch (hookError) {
console.error('[LogFuelScreen] Hook error:', hookError);
error = hookError;
}
const handleEdit = (log: FuelLogResponse) => {
if (!log || !log.id) {
console.error('[LogFuelScreen] Invalid log data for edit:', log);
return;
}
try {
setEditingLog(log);
} catch (error) {
console.error('[LogFuelScreen] Error setting editing log:', error);
}
};
const handleDelete = async (_logId: string) => {
try {
queryClient.invalidateQueries({ queryKey: ['fuelLogs'] });
queryClient.invalidateQueries({ queryKey: ['fuelLogsStats'] });
} catch (error) {
console.error('Failed to refresh fuel logs after delete:', error);
}
};
const handleSaveEdit = async (id: string, data: UpdateFuelLogRequest) => {
try {
await fuelLogsApi.update(id, data);
queryClient.invalidateQueries({ queryKey: ['fuelLogs'] });
queryClient.invalidateQueries({ queryKey: ['fuelLogsStats'] });
setEditingLog(null);
} catch (error) {
console.error('Failed to update fuel log:', error);
throw error;
}
};
const handleCloseEdit = () => setEditingLog(null);
if (error) {
return (
Failed to load fuel logs
);
}
if (isLoading === undefined) {
return (
Initializing fuel logs...
);
}
return (
{
// Refresh dependent data
try {
queryClient.invalidateQueries({ queryKey: ['fuelLogs'] });
queryClient.invalidateQueries({ queryKey: ['fuelLogsStats'] });
} catch {}
// Navigate back if we have history; otherwise go to Vehicles
if (canGoBack()) {
goBack();
} else {
navigateToScreen('Vehicles', { source: 'fuel-log-added' });
}
}} />
{isLoading ? (
Loading fuel logs...
) : (
)}
);
};
interface AddVehicleScreenProps {
onBack: () => void;
onAdded: () => void;
}
const AddVehicleScreen: React.FC = ({ onBack, onAdded }) => {
const { optimisticCreateVehicle } = useOptimisticVehicles([]);
const handleCreateVehicle = async (data: CreateVehicleRequest) => {
try {
await optimisticCreateVehicle(data);
onAdded();
} catch (error) {
console.error('Failed to create vehicle:', error);
}
};
return (
);
};
function App() {
const { isLoading, isAuthenticated, loginWithRedirect, user } = useAuth0();
const [_isPending, startTransition] = useTransition();
// Initialize data synchronization
const { prefetchForNavigation } = useDataSync();
// Enhanced navigation and user state management
const {
activeScreen,
vehicleSubScreen,
navigateToScreen,
navigateToVehicleSubScreen,
goBack,
canGoBack,
} = useNavigationStore();
const { setUserProfile } = useUserStore();
// Mobile mode detection - detect mobile screen size with responsive updates
const [mobileMode, setMobileMode] = useState(() => {
if (typeof window !== 'undefined') {
return window.innerWidth <= 768;
}
return false;
});
const [selectedVehicle, setSelectedVehicle] = useState(null);
const [showAddVehicle, setShowAddVehicle] = useState(false);
// Update mobile mode on window resize
useEffect(() => {
const checkMobileMode = () => {
const isMobile = window.innerWidth <= 768 ||
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
console.log('Window width:', window.innerWidth, 'User agent mobile:', /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent), 'Mobile mode:', isMobile);
setMobileMode(isMobile);
};
// Check on mount
checkMobileMode();
window.addEventListener('resize', checkMobileMode);
return () => window.removeEventListener('resize', checkMobileMode);
}, []);
// Update user profile when authenticated
useEffect(() => {
if (isAuthenticated && user) {
setUserProfile(user);
}
}, [isAuthenticated, user, setUserProfile]);
// Handle mobile back button and navigation errors
useEffect(() => {
const handlePopState = (event: PopStateEvent) => {
event.preventDefault();
if (canGoBack() && mobileMode) {
goBack();
}
};
if (mobileMode) {
window.addEventListener('popstate', handlePopState);
return () => window.removeEventListener('popstate', handlePopState);
}
return undefined;
}, [goBack, canGoBack, mobileMode]);
// Mobile navigation items
const mobileNavItems: NavigationItem[] = [
{ key: "Dashboard", label: "Dashboard", icon: },
{ key: "Vehicles", label: "Vehicles", icon: },
{ key: "Log Fuel", label: "Log Fuel", icon: },
{ key: "Settings", label: "Settings", icon: },
];
console.log('MotoVaultPro status:', { isLoading, isAuthenticated, mobileMode, activeScreen, vehicleSubScreen, userAgent: navigator.userAgent });
// Enhanced navigation handlers for mobile
const handleVehicleSelect = useCallback((vehicle: Vehicle) => {
setSelectedVehicle(vehicle);
navigateToVehicleSubScreen('detail', vehicle.id, { source: 'vehicle-list' });
}, [navigateToVehicleSubScreen]);
const handleAddVehicle = useCallback(() => {
setShowAddVehicle(true);
navigateToVehicleSubScreen('add', undefined, { source: 'vehicle-list' });
}, [navigateToVehicleSubScreen]);
const handleBackToList = useCallback(() => {
setSelectedVehicle(null);
setShowAddVehicle(false);
navigateToVehicleSubScreen('list', undefined, { source: 'back-navigation' });
}, [navigateToVehicleSubScreen]);
const handleVehicleAdded = useCallback(() => {
setShowAddVehicle(false);
navigateToVehicleSubScreen('list', undefined, { source: 'vehicle-added' });
}, [navigateToVehicleSubScreen]);
// Enhanced debug component
const DebugInfo = () => (
);
// Mobile settings now uses the dedicated MobileSettingsScreen component
const SettingsScreen = MobileSettingsScreen;
if (isLoading) {
if (mobileMode) {
return (
);
}
return (
);
}
if (!isAuthenticated) {
if (mobileMode) {
return (
Welcome to MotoVaultPro
Your personal vehicle management platform
);
}
return (
MotoVaultPro
Your personal vehicle management platform
);
}
// Mobile app rendering
if (mobileMode) {
return (
{activeScreen === "Dashboard" && (
)}
{activeScreen === "Vehicles" && (
{vehicleSubScreen === 'add' || showAddVehicle ? (
) : selectedVehicle && (vehicleSubScreen === 'detail') ? (
navigateToScreen("Log Fuel")}
/>
) : (
)}
)}
{activeScreen === "Log Fuel" && (
)}
{activeScreen === "Settings" && (
)}
startTransition(() => {
// Prefetch data for the target screen
prefetchForNavigation(screen);
// Reset states first, then navigate to prevent race conditions
if (screen !== 'Vehicles') {
setSelectedVehicle(null); // Reset selected vehicle when leaving Vehicles
}
if (screen !== 'Vehicles' || vehicleSubScreen !== 'add') {
setShowAddVehicle(false); // Reset add vehicle form when appropriate
}
// Navigate after state cleanup
navigateToScreen(screen as any, { source: 'bottom-navigation' });
})}
/>
);
}
// Desktop app rendering (fallback)
return (
} />
Processing login...} />
} />
} />
} />
Maintenance (TODO)} />
Stations (TODO)} />
} />
} />
);
}
export default App;