feat: Add online user guide with screenshots (#203) #204

Merged
egullickson merged 10 commits from issue-203-add-online-user-guide into main 2026-02-16 01:40:36 +00:00
17 changed files with 652 additions and 3 deletions
Showing only changes of commit 864da55cec - Show all commits

View File

@@ -47,6 +47,9 @@ const AdminLogsMobileScreen = lazy(() => import('./features/admin/mobile/AdminLo
const AdminCommunityStationsPage = lazy(() => import('./features/admin/pages/AdminCommunityStationsPage').then(m => ({ default: m.AdminCommunityStationsPage }))); const AdminCommunityStationsPage = lazy(() => import('./features/admin/pages/AdminCommunityStationsPage').then(m => ({ default: m.AdminCommunityStationsPage })));
const AdminCommunityStationsMobileScreen = lazy(() => import('./features/admin/mobile/AdminCommunityStationsMobileScreen').then(m => ({ default: m.AdminCommunityStationsMobileScreen }))); const AdminCommunityStationsMobileScreen = lazy(() => import('./features/admin/mobile/AdminCommunityStationsMobileScreen').then(m => ({ default: m.AdminCommunityStationsMobileScreen })));
// Public pages (lazy-loaded)
const GuidePage = lazy(() => import('./pages/GuidePage/GuidePage').then(m => ({ default: m.GuidePage })));
// Auth pages (lazy-loaded) // Auth pages (lazy-loaded)
const SignupPage = lazy(() => import('./features/auth/pages/SignupPage').then(m => ({ default: m.SignupPage }))); const SignupPage = lazy(() => import('./features/auth/pages/SignupPage').then(m => ({ default: m.SignupPage })));
const VerifyEmailPage = lazy(() => import('./features/auth/pages/VerifyEmailPage').then(m => ({ default: m.VerifyEmailPage }))); const VerifyEmailPage = lazy(() => import('./features/auth/pages/VerifyEmailPage').then(m => ({ default: m.VerifyEmailPage })));
@@ -368,7 +371,7 @@ function App() {
// Skip on auth routes -- their query params must survive until Auth0 SDK processes them // Skip on auth routes -- their query params must survive until Auth0 SDK processes them
useEffect(() => { useEffect(() => {
const path = window.location.pathname; const path = window.location.pathname;
if (path === '/callback' || path === '/signup' || path === '/verify-email') return; if (path === '/callback' || path === '/signup' || path === '/verify-email' || path === '/guide') return;
const screen = routeToScreen[path]; const screen = routeToScreen[path];
if (screen && screen !== activeScreen) { if (screen && screen !== activeScreen) {
navigateToScreen(screen, { source: 'url-sync' }); navigateToScreen(screen, { source: 'url-sync' });
@@ -380,7 +383,7 @@ function App() {
// Auth0 SDK needs for handleRedirectCallback (child effects fire before parent effects) // Auth0 SDK needs for handleRedirectCallback (child effects fire before parent effects)
useEffect(() => { useEffect(() => {
const path = window.location.pathname; const path = window.location.pathname;
if (path === '/callback' || path === '/signup' || path === '/verify-email') return; if (path === '/callback' || path === '/signup' || path === '/verify-email' || path === '/guide') return;
const targetPath = screenToRoute[activeScreen]; const targetPath = screenToRoute[activeScreen];
if (targetPath && path !== targetPath) { if (targetPath && path !== targetPath) {
window.history.replaceState(null, '', targetPath); window.history.replaceState(null, '', targetPath);
@@ -499,8 +502,9 @@ function App() {
const isSignupRoute = location.pathname === '/signup'; const isSignupRoute = location.pathname === '/signup';
const isVerifyEmailRoute = location.pathname === '/verify-email'; const isVerifyEmailRoute = location.pathname === '/verify-email';
const isOnboardingRoute = location.pathname === '/onboarding'; const isOnboardingRoute = location.pathname === '/onboarding';
const isGuideRoute = location.pathname === '/guide';
const isAuthRoute = isSignupRoute || isVerifyEmailRoute || isOnboardingRoute; const isAuthRoute = isSignupRoute || isVerifyEmailRoute || isOnboardingRoute;
const shouldShowHomePage = !isGarageRoute && !isCallbackRoute && !isAuthRoute; const shouldShowHomePage = !isGarageRoute && !isCallbackRoute && !isAuthRoute && !isGuideRoute;
const [callbackTimedOut, setCallbackTimedOut] = useState(false); const [callbackTimedOut, setCallbackTimedOut] = useState(false);
useEffect(() => { useEffect(() => {
@@ -635,6 +639,21 @@ function App() {
); );
} }
if (isGuideRoute) {
return (
<ThemeProvider>
<React.Suspense fallback={
<div className="flex items-center justify-center min-h-screen bg-nero">
<div className="text-lg text-avus">Loading guide...</div>
</div>
}>
<GuidePage />
</React.Suspense>
<DebugInfo />
</ThemeProvider>
);
}
// Signup route is public - no authentication required // Signup route is public - no authentication required
if (isSignupRoute) { if (isSignupRoute) {
return ( return (

View File

@@ -0,0 +1,238 @@
import { useState, useEffect, useCallback, Suspense } from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import { useNavigate } from 'react-router-dom';
import { GuideTableOfContents } from './GuideTableOfContents';
import { guideSections } from './guideTypes';
import {
GettingStartedSection,
DashboardSection,
VehiclesSection,
FuelLogsSection,
MaintenanceSection,
GasStationsSection,
DocumentsSection,
SettingsSection,
SubscriptionSection,
MobileExperienceSection,
} from './sections';
export const GuidePage = () => {
const { loginWithRedirect, isAuthenticated } = useAuth0();
const navigate = useNavigate();
const [activeSection, setActiveSection] = useState(guideSections[0].id);
const [isScrolled, setIsScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const handleAuthAction = useCallback(() => {
if (isAuthenticated) {
navigate('/garage');
return;
}
loginWithRedirect({ appState: { returnTo: '/garage' } });
}, [isAuthenticated, navigate, loginWithRedirect]);
const handleSignup = useCallback(() => {
navigate('/signup');
}, [navigate]);
// Track scroll position for nav background and active section
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
// Determine active section from scroll position
const sectionElements = guideSections.map((s) => ({
id: s.id,
element: document.getElementById(s.id),
}));
for (let i = sectionElements.length - 1; i >= 0; i--) {
const { id, element } = sectionElements[i];
if (element) {
const rect = element.getBoundingClientRect();
if (rect.top <= 120) {
setActiveSection(id);
break;
}
}
}
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const sectionFallback = (
<div className="py-8 text-center text-titanio/50">Loading section...</div>
);
return (
<div className="min-h-screen bg-nero text-avus">
{/* Navigation Bar - matches HomePage style */}
<nav
className={`fixed top-0 left-0 right-0 z-50 transition-colors duration-300 ${
isScrolled ? 'bg-nero/95 backdrop-blur-sm' : 'bg-nero'
}`}
>
<div className="w-full px-4 md:px-8 lg:px-12">
<div className="flex justify-between items-center h-16">
<div className="flex-shrink-0">
<a href="/" className="flex items-center">
<img
src="/images/logos/motovaultpro-title-slogan.png"
alt="MotoVaultPro - Precision Vehicle Management"
className="h-8 md:h-10 w-auto"
/>
</a>
</div>
{/* Desktop Menu */}
<div className="hidden md:flex items-center space-x-8">
<a href="/#home" className="text-white/75 hover:text-white transition-colors">
Home
</a>
<a href="/#features" className="text-white/75 hover:text-white transition-colors">
Features
</a>
<a href="/#about" className="text-white/75 hover:text-white transition-colors">
About
</a>
<a
href="/guide"
className="text-primary-400 font-semibold transition-colors"
>
Guide
</a>
<button
onClick={handleSignup}
className="border border-primary-500/90 text-primary-500 hover:bg-primary-500/10 hover:border-primary-500 font-semibold py-2 px-6 rounded-lg transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-primary-500/50"
>
Sign Up
</button>
<button
onClick={handleAuthAction}
className="bg-primary-500 hover:bg-primary-600 text-white font-semibold py-2 px-6 rounded-lg transition-colors duration-300 shadow-lg shadow-black/30 focus:outline-none focus:ring-2 focus:ring-primary-500/50"
>
Login
</button>
</div>
{/* Mobile Menu Button */}
<div className="md:hidden">
<button
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
className="text-white/80 hover:text-white focus:outline-none"
>
<svg
className="h-6 w-6"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
stroke="currentColor"
>
{mobileMenuOpen ? (
<path d="M6 18L18 6M6 6l12 12" />
) : (
<path d="M4 6h16M4 12h16M4 18h16" />
)}
</svg>
</button>
</div>
</div>
{/* Mobile Menu */}
{mobileMenuOpen && (
<div className="md:hidden py-4 space-y-3 bg-nero/95 backdrop-blur-sm border-t border-white/10">
<a href="/" className="block text-white/75 hover:text-white transition-colors py-2">
Home
</a>
<a href="/#features" className="block text-white/75 hover:text-white transition-colors py-2">
Features
</a>
<a href="/#about" className="block text-white/75 hover:text-white transition-colors py-2">
About
</a>
<a href="/guide" className="block text-primary-400 font-semibold py-2">
Guide
</a>
<button
onClick={handleSignup}
className="w-full border border-primary-500/90 text-primary-500 hover:bg-primary-500/10 font-semibold py-2 px-6 rounded-lg transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-primary-500/50"
>
Sign Up
</button>
<button
onClick={handleAuthAction}
className="w-full bg-primary-500 hover:bg-primary-600 text-white font-semibold py-2 px-6 rounded-lg transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-primary-500/50"
>
Login
</button>
</div>
)}
</div>
</nav>
{/* Page Content */}
<div className="pt-20 px-4 md:px-8 lg:px-12 max-w-7xl mx-auto">
{/* Page Header */}
<div className="py-8 md:py-12 border-b border-white/10 mb-8">
<h1 className="text-3xl md:text-4xl font-bold text-avus mb-3">
User Guide
</h1>
<p className="text-lg text-titanio/70">
Precision Vehicle Management -- Track every mile. Own every detail.
</p>
</div>
{/* Layout: TOC sidebar + content */}
<div className="flex flex-col md:flex-row gap-8 pb-16">
<GuideTableOfContents activeSection={activeSection} />
<main className="flex-1 min-w-0">
<Suspense fallback={sectionFallback}>
<GettingStartedSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<DashboardSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<VehiclesSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<FuelLogsSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<MaintenanceSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<GasStationsSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<DocumentsSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<SettingsSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<SubscriptionSection />
</Suspense>
<Suspense fallback={sectionFallback}>
<MobileExperienceSection />
</Suspense>
</main>
</div>
</div>
{/* Footer */}
<footer className="bg-black text-white py-8 px-4 md:px-8 border-t border-white/10">
<div className="max-w-7xl mx-auto text-center">
<p className="text-white/50">
&copy; {new Date().getFullYear()} FB Technologies LLC. All rights reserved.
</p>
</div>
</footer>
</div>
);
};

View File

@@ -0,0 +1,92 @@
import { useState, useEffect } from 'react';
import { Accordion, AccordionSummary, AccordionDetails } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { guideSections } from './guideTypes';
interface GuideTableOfContentsProps {
activeSection: string;
}
export const GuideTableOfContents = ({ activeSection }: GuideTableOfContentsProps) => {
const [isMobile, setIsMobile] = useState(false);
const [tocExpanded, setTocExpanded] = useState(false);
useEffect(() => {
const check = () => setIsMobile(window.innerWidth < 768);
check();
window.addEventListener('resize', check);
return () => window.removeEventListener('resize', check);
}, []);
const handleClick = (sectionId: string) => {
const element = document.getElementById(sectionId);
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
if (isMobile) {
setTocExpanded(false);
}
};
const tocContent = (
<nav aria-label="Table of contents">
<ul className="space-y-1">
{guideSections.map((section) => (
<li key={section.id}>
<button
onClick={() => handleClick(section.id)}
className={`w-full text-left px-3 py-3 rounded-md text-sm transition-colors ${
activeSection === section.id
? 'bg-primary-500/15 text-primary-400 font-semibold'
: 'text-titanio/70 hover:text-titanio hover:bg-white/5'
}`}
>
{section.title}
</button>
</li>
))}
</ul>
</nav>
);
if (isMobile) {
return (
<div className="mb-6">
<Accordion
expanded={tocExpanded}
onChange={(_, expanded) => setTocExpanded(expanded)}
sx={{
backgroundColor: 'rgba(255,255,255,0.03)',
border: '1px solid rgba(255,255,255,0.08)',
borderRadius: '8px !important',
'&:before': { display: 'none' },
}}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon sx={{ color: 'rgba(168,184,192,0.7)' }} />}
sx={{
color: 'rgba(242,243,246,0.9)',
fontWeight: 600,
minHeight: 48,
'& .MuiAccordionSummary-content': { margin: '12px 0' },
}}
>
Table of Contents
</AccordionSummary>
<AccordionDetails sx={{ pt: 0 }}>
{tocContent}
</AccordionDetails>
</Accordion>
</div>
);
}
return (
<aside className="sticky top-20 w-64 flex-shrink-0 max-h-[calc(100vh-6rem)] overflow-y-auto pr-4">
<h2 className="text-sm font-semibold text-titanio/50 uppercase tracking-wider mb-4 px-3">
Contents
</h2>
{tocContent}
</aside>
);
};

View File

@@ -0,0 +1,26 @@
interface GuideScreenshotProps {
src: string;
alt: string;
caption?: string;
mobile?: boolean;
}
export const GuideScreenshot = ({ src, alt, caption, mobile }: GuideScreenshotProps) => {
return (
<figure className={`my-6 ${mobile ? 'max-w-[375px]' : 'max-w-4xl'} mx-auto`}>
<div className="rounded-lg overflow-hidden border border-white/10 shadow-lg shadow-black/20">
<img
src={src}
alt={alt}
loading="lazy"
className="w-full h-auto"
/>
</div>
{caption && (
<figcaption className="mt-2 text-center text-sm text-titanio/70 italic">
{caption}
</figcaption>
)}
</figure>
);
};

View File

@@ -0,0 +1,68 @@
import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
} from '@mui/material';
interface GuideTableProps {
headers: string[];
rows: string[][];
}
export const GuideTable = ({ headers, rows }: GuideTableProps) => {
return (
<TableContainer
component={Paper}
sx={{
my: 3,
backgroundColor: 'rgba(255,255,255,0.03)',
border: '1px solid rgba(255,255,255,0.08)',
borderRadius: 2,
}}
>
<Table size="small">
<TableHead>
<TableRow>
{headers.map((header, idx) => (
<TableCell
key={idx}
sx={{
fontWeight: 600,
color: 'rgba(168,184,192,0.9)',
borderBottom: '1px solid rgba(255,255,255,0.08)',
fontSize: '0.85rem',
whiteSpace: 'nowrap',
}}
>
{header}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.map((row, rowIdx) => (
<TableRow key={rowIdx}>
{row.map((cell, cellIdx) => (
<TableCell
key={cellIdx}
sx={{
color: 'rgba(168,184,192,0.75)',
borderBottom: '1px solid rgba(255,255,255,0.04)',
fontSize: '0.85rem',
verticalAlign: 'top',
}}
>
{cell}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};

View File

@@ -0,0 +1,114 @@
export interface GuideSubSection {
id: string;
title: string;
}
export interface GuideSection {
id: string;
title: string;
subSections: GuideSubSection[];
}
export const guideSections: GuideSection[] = [
{
id: 'getting-started',
title: '1. Getting Started',
subSections: [
{ id: 'creating-an-account', title: 'Creating an Account' },
{ id: 'logging-in', title: 'Logging In' },
{ id: 'onboarding', title: 'Onboarding' },
{ id: 'trouble-logging-in', title: 'Trouble Logging In' },
],
},
{
id: 'dashboard',
title: '2. Dashboard',
subSections: [
{ id: 'your-fleet-overview', title: 'Your Fleet Overview' },
{ id: 'quick-actions', title: 'Quick Actions' },
],
},
{
id: 'vehicles',
title: '3. Vehicles',
subSections: [
{ id: 'viewing-your-vehicles', title: 'Viewing Your Vehicles' },
{ id: 'adding-a-vehicle', title: 'Adding a Vehicle' },
{ id: 'vin-decode', title: 'VIN Decode' },
{ id: 'vehicle-detail-page', title: 'Vehicle Detail Page' },
{ id: 'editing-a-vehicle', title: 'Editing a Vehicle' },
{ id: 'deleting-a-vehicle', title: 'Deleting a Vehicle' },
],
},
{
id: 'fuel-logs',
title: '4. Fuel Logs',
subSections: [
{ id: 'fuel-logs-overview', title: 'Fuel Logs Overview' },
{ id: 'logging-fuel', title: 'Logging Fuel' },
{ id: 'receipt-scanning', title: 'Receipt Scanning' },
{ id: 'editing-and-deleting-fuel-logs', title: 'Editing and Deleting Fuel Logs' },
],
},
{
id: 'maintenance',
title: '5. Maintenance',
subSections: [
{ id: 'maintenance-records', title: 'Maintenance Records' },
{ id: 'adding-a-maintenance-record', title: 'Adding a Maintenance Record' },
{ id: 'maintenance-schedules', title: 'Maintenance Schedules' },
{ id: 'creating-a-schedule', title: 'Creating a Schedule' },
],
},
{
id: 'gas-stations',
title: '6. Gas Stations',
subSections: [
{ id: 'finding-stations', title: 'Finding Stations' },
{ id: 'saved-stations', title: 'Saved Stations' },
{ id: 'premium-93-stations', title: 'Premium 93 Stations' },
],
},
{
id: 'documents',
title: '7. Documents',
subSections: [
{ id: 'documents-overview', title: 'Documents Overview' },
{ id: 'adding-a-document', title: 'Adding a Document' },
{ id: 'document-types', title: 'Document Types' },
],
},
{
id: 'settings',
title: '8. Settings',
subSections: [
{ id: 'profile', title: 'Profile' },
{ id: 'security-and-privacy', title: 'Security and Privacy' },
{ id: 'subscription', title: 'Subscription' },
{ id: 'notifications', title: 'Notifications' },
{ id: 'appearance-and-units', title: 'Appearance and Units' },
{ id: 'data-import-and-export', title: 'Data Import and Export' },
{ id: 'account-actions', title: 'Account Actions' },
],
},
{
id: 'subscription-tiers',
title: '9. Subscription Tiers and Pro Features',
subSections: [
{ id: 'tier-comparison', title: 'Tier Comparison' },
{ id: 'vin-camera-scanning', title: 'VIN Camera Scanning (Pro)' },
{ id: 'fuel-receipt-scanning', title: 'Fuel Receipt Scanning (Pro)' },
{ id: 'maintenance-receipt-scanning', title: 'Maintenance Receipt Scanning (Pro)' },
{ id: 'maintenance-manual-pdf', title: 'Maintenance Manual PDF (Pro)' },
{ id: 'email-ingestion', title: 'Email Ingestion (Pro)' },
{ id: 'shared-vehicle-documents', title: 'Shared Vehicle Documents (Pro)' },
{ id: 'community-station-submissions', title: 'Community Station Submissions (Pro)' },
{ id: 'managing-your-subscription', title: 'Managing Your Subscription' },
],
},
{
id: 'mobile-experience',
title: '10. Mobile Experience',
subSections: [],
},
];

View File

@@ -0,0 +1,8 @@
export const DashboardSection = () => {
return (
<section id="dashboard" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">2. Dashboard</h2>
<p className="text-titanio/70">Content loading in Milestone 2...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const DocumentsSection = () => {
return (
<section id="documents" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">7. Documents</h2>
<p className="text-titanio/70">Content loading in Milestone 3...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const FuelLogsSection = () => {
return (
<section id="fuel-logs" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">4. Fuel Logs</h2>
<p className="text-titanio/70">Content loading in Milestone 2...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const GasStationsSection = () => {
return (
<section id="gas-stations" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">6. Gas Stations</h2>
<p className="text-titanio/70">Content loading in Milestone 3...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const GettingStartedSection = () => {
return (
<section id="getting-started" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">1. Getting Started</h2>
<p className="text-titanio/70">Content loading in Milestone 2...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const MaintenanceSection = () => {
return (
<section id="maintenance" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">5. Maintenance</h2>
<p className="text-titanio/70">Content loading in Milestone 2...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const MobileExperienceSection = () => {
return (
<section id="mobile-experience" className="py-8 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">10. Mobile Experience</h2>
<p className="text-titanio/70">Content loading in Milestone 3...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const SettingsSection = () => {
return (
<section id="settings" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">8. Settings</h2>
<p className="text-titanio/70">Content loading in Milestone 3...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const SubscriptionSection = () => {
return (
<section id="subscription-tiers" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">9. Subscription Tiers and Pro Features</h2>
<p className="text-titanio/70">Content loading in Milestone 3...</p>
</section>
);
};

View File

@@ -0,0 +1,8 @@
export const VehiclesSection = () => {
return (
<section id="vehicles" className="py-8 border-b border-white/5 scroll-mt-24">
<h2 className="text-2xl font-bold text-avus mb-4">3. Vehicles</h2>
<p className="text-titanio/70">Content loading in Milestone 2...</p>
</section>
);
};

View File

@@ -0,0 +1,12 @@
import { lazy } from 'react';
export const GettingStartedSection = lazy(() => import('./GettingStartedSection').then(m => ({ default: m.GettingStartedSection })));
export const DashboardSection = lazy(() => import('./DashboardSection').then(m => ({ default: m.DashboardSection })));
export const VehiclesSection = lazy(() => import('./VehiclesSection').then(m => ({ default: m.VehiclesSection })));
export const FuelLogsSection = lazy(() => import('./FuelLogsSection').then(m => ({ default: m.FuelLogsSection })));
export const MaintenanceSection = lazy(() => import('./MaintenanceSection').then(m => ({ default: m.MaintenanceSection })));
export const GasStationsSection = lazy(() => import('./GasStationsSection').then(m => ({ default: m.GasStationsSection })));
export const DocumentsSection = lazy(() => import('./DocumentsSection').then(m => ({ default: m.DocumentsSection })));
export const SettingsSection = lazy(() => import('./SettingsSection').then(m => ({ default: m.SettingsSection })));
export const SubscriptionSection = lazy(() => import('./SubscriptionSection').then(m => ({ default: m.SubscriptionSection })));
export const MobileExperienceSection = lazy(() => import('./MobileExperienceSection').then(m => ({ default: m.MobileExperienceSection })));