MVP with new UX

This commit is contained in:
Eric Gullickson
2025-08-09 17:45:54 -05:00
parent 8f5117a4e2
commit d60c3ec00e
18 changed files with 1572 additions and 573 deletions

View File

@@ -1,50 +1,238 @@
/**
* @ai-summary Main app component with routing
* @ai-summary Main app component with routing and mobile navigation
*/
import { useState, useEffect } from 'react';
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 { VehiclesPage } from './features/vehicles/pages/VehiclesPage';
import { VehiclesMobileScreen } from './features/vehicles/mobile/VehiclesMobileScreen';
import { VehicleDetailMobile } from './features/vehicles/mobile/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 { Vehicle } from './features/vehicles/types/vehicles.types';
function App() {
const { isLoading, isAuthenticated, loginWithRedirect } = useAuth0();
// Mobile navigation state - detect mobile screen size with responsive updates
const [mobileMode, setMobileMode] = useState(() => {
if (typeof window !== 'undefined') {
return window.innerWidth <= 768;
}
return false;
});
const [activeScreen, setActiveScreen] = useState("Vehicles");
const [selectedVehicle, setSelectedVehicle] = useState<Vehicle | null>(null);
// 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);
}, []);
// Mobile navigation items
const mobileNavItems: NavigationItem[] = [
{ key: "Dashboard", label: "Dashboard", icon: <HomeRoundedIcon /> },
{ key: "Vehicles", label: "Vehicles", icon: <DirectionsCarRoundedIcon /> },
{ key: "Log Fuel", label: "Log Fuel", icon: <LocalGasStationRoundedIcon /> },
{ key: "Settings", label: "Settings", icon: <SettingsRoundedIcon /> },
];
console.log('MotoVaultPro status:', { isLoading, isAuthenticated, mobileMode, userAgent: navigator.userAgent });
// Debug component for testing
const DebugInfo = () => (
<div className="fixed bottom-0 right-0 bg-black/80 text-white p-2 text-xs z-50 rounded-tl-lg">
Mode: {mobileMode ? 'Mobile' : 'Desktop'} | Auth: {isAuthenticated ? 'Yes' : 'No'} | Screen: {typeof window !== 'undefined' ? window.innerWidth : 'N/A'}px
</div>
);
// Placeholder screens for mobile
const DashboardScreen = () => (
<div className="space-y-4">
<GlassCard>
<div className="text-center py-12">
<h2 className="text-lg font-semibold text-slate-800 mb-2">Dashboard</h2>
<p className="text-slate-500">Coming soon - Vehicle insights and analytics</p>
</div>
</GlassCard>
</div>
);
const LogFuelScreen = () => (
<div className="space-y-4">
<GlassCard>
<div className="text-center py-12">
<h2 className="text-lg font-semibold text-slate-800 mb-2">Log Fuel</h2>
<p className="text-slate-500">Coming soon - Fuel logging functionality</p>
</div>
</GlassCard>
</div>
);
const SettingsScreen = () => (
<div className="space-y-4">
<GlassCard>
<div className="text-center py-12">
<h2 className="text-lg font-semibold text-slate-800 mb-2">Settings</h2>
<p className="text-slate-500">Coming soon - App settings and preferences</p>
</div>
</GlassCard>
</div>
);
if (isLoading) {
if (mobileMode) {
return (
<ThemeProvider theme={md3Theme}>
<CssBaseline />
<Layout mobileMode={true}>
<div className="flex items-center justify-center h-64">
<div className="text-slate-500">Loading...</div>
</div>
</Layout>
</ThemeProvider>
);
}
return (
<div className="flex items-center justify-center min-h-screen">
<div className="text-lg">Loading...</div>
</div>
<ThemeProvider theme={md3Theme}>
<CssBaseline />
<div className="flex items-center justify-center min-h-screen">
<div className="text-lg">Loading...</div>
</div>
</ThemeProvider>
);
}
if (!isAuthenticated) {
if (mobileMode) {
return (
<ThemeProvider theme={md3Theme}>
<CssBaseline />
<Layout mobileMode={true}>
<div className="space-y-6 flex flex-col items-center justify-center min-h-[400px]">
<div className="text-center">
<h1 className="text-2xl font-bold text-slate-800 mb-3">Welcome to MotoVaultPro</h1>
<p className="text-slate-600 mb-6 text-sm">Your personal vehicle management platform</p>
<button
onClick={() => loginWithRedirect()}
className="h-12 px-8 rounded-2xl text-white font-medium shadow-lg active:scale-[0.99] transition bg-gradient-moto"
>
Login to Continue
</button>
</div>
</div>
<DebugInfo />
</Layout>
</ThemeProvider>
);
}
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-center">
<h1 className="text-4xl font-bold text-gray-900 mb-4">MotoVaultPro</h1>
<p className="text-gray-600 mb-8">Your personal vehicle management platform</p>
<Button onClick={() => loginWithRedirect()}>
Login to Continue
</Button>
<ThemeProvider theme={md3Theme}>
<CssBaseline />
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-center max-w-md mx-auto px-6">
<h1 className="text-4xl font-bold text-gray-900 mb-4">MotoVaultPro</h1>
<p className="text-gray-600 mb-8">Your personal vehicle management platform</p>
<Button onClick={() => loginWithRedirect()}>
Login to Continue
</Button>
</div>
<DebugInfo />
</div>
</div>
</ThemeProvider>
);
}
// Mobile app rendering
if (mobileMode) {
return (
<ThemeProvider theme={md3Theme}>
<CssBaseline />
<Layout mobileMode={true}>
<AnimatePresence mode="wait">
{activeScreen === "Dashboard" && (
<motion.div key="dashboard" initial={{opacity:0, y:8}} animate={{opacity:1, y:0}} exit={{opacity:0, y:-8}}>
<DashboardScreen />
</motion.div>
)}
{activeScreen === "Vehicles" && (
<motion.div key="vehicles" initial={{opacity:0, y:8}} animate={{opacity:1, y:0}} exit={{opacity:0, y:-8}} className="space-y-6">
{selectedVehicle ? (
<VehicleDetailMobile
vehicle={selectedVehicle}
onBack={() => setSelectedVehicle(null)}
onLogFuel={() => setActiveScreen("Log Fuel")}
/>
) : (
<VehiclesMobileScreen
onVehicleSelect={(vehicle) => setSelectedVehicle(vehicle)}
/>
)}
</motion.div>
)}
{activeScreen === "Log Fuel" && (
<motion.div key="logfuel" initial={{opacity:0, y:8}} animate={{opacity:1, y:0}} exit={{opacity:0, y:-8}}>
<LogFuelScreen />
</motion.div>
)}
{activeScreen === "Settings" && (
<motion.div key="settings" initial={{opacity:0, y:8}} animate={{opacity:1, y:0}} exit={{opacity:0, y:-8}}>
<SettingsScreen />
</motion.div>
)}
</AnimatePresence>
<DebugInfo />
</Layout>
<BottomNavigation
items={mobileNavItems}
activeItem={activeScreen}
onItemSelect={setActiveScreen}
/>
</ThemeProvider>
);
}
// Desktop app rendering (fallback)
return (
<Layout>
<Routes>
<Route path="/" element={<Navigate to="/vehicles" replace />} />
<Route path="/vehicles" element={<VehiclesPage />} />
<Route path="/vehicles/:id" element={<div>Vehicle Details (TODO)</div>} />
<Route path="/fuel-logs" element={<div>Fuel Logs (TODO)</div>} />
<Route path="/maintenance" element={<div>Maintenance (TODO)</div>} />
<Route path="/stations" element={<div>Stations (TODO)</div>} />
<Route path="*" element={<Navigate to="/vehicles" replace />} />
</Routes>
</Layout>
<ThemeProvider theme={md3Theme}>
<CssBaseline />
<Layout mobileMode={false}>
<Routes>
<Route path="/" element={<Navigate to="/vehicles" replace />} />
<Route path="/vehicles" element={<VehiclesPage />} />
<Route path="/vehicles/:id" element={<div>Vehicle Details (TODO)</div>} />
<Route path="/fuel-logs" element={<div>Fuel Logs (TODO)</div>} />
<Route path="/maintenance" element={<div>Maintenance (TODO)</div>} />
<Route path="/stations" element={<div>Stations (TODO)</div>} />
<Route path="*" element={<Navigate to="/vehicles" replace />} />
</Routes>
<DebugInfo />
</Layout>
</ThemeProvider>
);
}