chore: UX design audit cleanup and receipt flow improvements #186
@@ -81,7 +81,7 @@ import { useOptimisticVehicles } from './features/vehicles/hooks/useOptimisticVe
|
||||
import { CreateVehicleRequest } from './features/vehicles/types/vehicles.types';
|
||||
import { MobileSettingsScreen } from './features/settings/mobile/MobileSettingsScreen';
|
||||
import { SecurityMobileScreen } from './features/settings/mobile/SecurityMobileScreen';
|
||||
import { useNavigationStore, useUserStore } from './core/store';
|
||||
import { useNavigationStore, useUserStore, routeToScreen, screenToRoute } from './core/store';
|
||||
import { useNeedsVehicleSelection, useDowngrade } from './features/subscription/hooks/useSubscription';
|
||||
import { useVehicles } from './features/vehicles/hooks/useVehicles';
|
||||
import { VehicleSelectionDialog } from './features/subscription/components/VehicleSelectionDialog';
|
||||
@@ -364,6 +364,22 @@ function App() {
|
||||
const [selectedVehicle, setSelectedVehicle] = useState<Vehicle | null>(null);
|
||||
const [showAddVehicle, setShowAddVehicle] = useState(false);
|
||||
|
||||
// Sync browser URL to Zustand screen state on mount (enables direct URL navigation on mobile)
|
||||
useEffect(() => {
|
||||
const screen = routeToScreen[window.location.pathname];
|
||||
if (screen && screen !== activeScreen) {
|
||||
navigateToScreen(screen, { source: 'url-sync' });
|
||||
}
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps -- intentionally runs once on mount
|
||||
|
||||
// Sync Zustand screen changes back to browser URL (enables bookmarks and URL sharing)
|
||||
useEffect(() => {
|
||||
const targetPath = screenToRoute[activeScreen];
|
||||
if (targetPath && window.location.pathname !== targetPath) {
|
||||
window.history.replaceState(null, '', targetPath);
|
||||
}
|
||||
}, [activeScreen]);
|
||||
|
||||
// Update mobile mode on window resize
|
||||
useEffect(() => {
|
||||
const checkMobileMode = () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Export navigation store
|
||||
export { useNavigationStore } from './navigation';
|
||||
export { useNavigationStore, routeToScreen, screenToRoute } from './navigation';
|
||||
export type { MobileScreen, VehicleSubScreen } from './navigation';
|
||||
|
||||
// Export user store
|
||||
|
||||
@@ -5,6 +5,45 @@ import { safeStorage } from '../utils/safe-storage';
|
||||
export type MobileScreen = 'Dashboard' | 'Vehicles' | 'Log Fuel' | 'Maintenance' | 'Stations' | 'Documents' | 'Settings' | 'Security' | 'Subscription' | 'AdminUsers' | 'AdminCatalog' | 'AdminCommunityStations' | 'AdminEmailTemplates' | 'AdminBackup' | 'AdminLogs';
|
||||
export type VehicleSubScreen = 'list' | 'detail' | 'add' | 'edit';
|
||||
|
||||
/** Maps browser URL paths to mobile screen names for direct URL navigation */
|
||||
export const routeToScreen: Record<string, MobileScreen> = {
|
||||
'/garage': 'Dashboard',
|
||||
'/garage/dashboard': 'Dashboard',
|
||||
'/garage/vehicles': 'Vehicles',
|
||||
'/garage/fuel-logs': 'Log Fuel',
|
||||
'/garage/maintenance': 'Maintenance',
|
||||
'/garage/stations': 'Stations',
|
||||
'/garage/documents': 'Documents',
|
||||
'/garage/settings': 'Settings',
|
||||
'/garage/settings/security': 'Security',
|
||||
'/garage/settings/subscription': 'Subscription',
|
||||
'/garage/settings/admin/users': 'AdminUsers',
|
||||
'/garage/settings/admin/catalog': 'AdminCatalog',
|
||||
'/garage/settings/admin/community-stations': 'AdminCommunityStations',
|
||||
'/garage/settings/admin/email-templates': 'AdminEmailTemplates',
|
||||
'/garage/settings/admin/backup': 'AdminBackup',
|
||||
'/garage/settings/admin/logs': 'AdminLogs',
|
||||
};
|
||||
|
||||
/** Reverse mapping: mobile screen name to canonical URL path */
|
||||
export const screenToRoute: Record<MobileScreen, string> = {
|
||||
'Dashboard': '/garage/dashboard',
|
||||
'Vehicles': '/garage/vehicles',
|
||||
'Log Fuel': '/garage/fuel-logs',
|
||||
'Maintenance': '/garage/maintenance',
|
||||
'Stations': '/garage/stations',
|
||||
'Documents': '/garage/documents',
|
||||
'Settings': '/garage/settings',
|
||||
'Security': '/garage/settings/security',
|
||||
'Subscription': '/garage/settings/subscription',
|
||||
'AdminUsers': '/garage/settings/admin/users',
|
||||
'AdminCatalog': '/garage/settings/admin/catalog',
|
||||
'AdminCommunityStations': '/garage/settings/admin/community-stations',
|
||||
'AdminEmailTemplates': '/garage/settings/admin/email-templates',
|
||||
'AdminBackup': '/garage/settings/admin/backup',
|
||||
'AdminLogs': '/garage/settings/admin/logs',
|
||||
};
|
||||
|
||||
interface NavigationHistory {
|
||||
screen: MobileScreen;
|
||||
vehicleSubScreen?: VehicleSubScreen;
|
||||
@@ -196,7 +235,6 @@ export const useNavigationStore = create<NavigationState>()(
|
||||
name: 'motovaultpro-mobile-navigation',
|
||||
storage: createJSONStorage(() => safeStorage),
|
||||
partialize: (state) => ({
|
||||
activeScreen: state.activeScreen,
|
||||
vehicleSubScreen: state.vehicleSubScreen,
|
||||
selectedVehicleId: state.selectedVehicleId,
|
||||
formStates: state.formStates,
|
||||
|
||||
Reference in New Issue
Block a user