Overview
MotorDesk is built as a Progressive Web Application (PWA) using a modern React stack optimized for offline-first fleet management and electronic billing.
Technology Stack
Frontend Framework React 18.2 with TypeScript for type-safe component development
Build Tool Vite 7.3 for lightning-fast development and optimized production builds
State Management Redux Toolkit with Redux Saga for predictable state and side effects
PWA Support Vite PWA plugin for offline capabilities and app-like experience
Core Dependencies
{
"@reduxjs/toolkit" : "^2.11.2" ,
"redux-saga" : "^1.4.2" ,
"redux-persist" : "^6.0.0" ,
"localforage" : "^1.10.0" ,
"react-router-dom" : "^7.13.1" ,
"vite-plugin-pwa" : "^1.2.0"
}
Project Structure
src/
├── components/ # Reusable UI components
│ ├── auth/ # Authentication components
│ ├── customers/ # Customer management components
│ ├── layout/ # Layout components (headers, sidebars)
│ ├── products/ # Product management components
│ ├── sales/ # Sales and billing components
│ ├── ui/ # Base UI components
│ └── vehicles/ # Fleet vehicle components
├── pages/ # Route-level page components
│ ├── Login.tsx
│ ├── Home.tsx
│ ├── Sales.tsx
│ ├── Vehicles.tsx
│ ├── Customers.tsx
│ ├── Products.tsx
│ ├── Reports.tsx
│ └── Settings.tsx
├── routes/ # React Router configuration
├── store/ # Redux store and state management
│ ├── slices/ # Redux Toolkit slices
│ ├── index.ts # Store configuration
│ └── rootSaga.ts # Root saga for side effects
├── hooks/ # Custom React hooks
├── services/ # API and external service integrations
├── constants/ # Application constants and enums
├── data/ # Static data and mock data
└── assets/ # Static assets (images, icons)
Path Aliases
The application uses path aliases for cleaner imports, configured in vite.config.ts:28-41:
alias : {
"@" : path . resolve ( __dirname , "./src" ),
"@components" : path . resolve ( __dirname , "./src/components" ),
"@pages" : path . resolve ( __dirname , "./src/pages" ),
"@routes" : path . resolve ( __dirname , "./src/routes" ),
"@hooks" : path . resolve ( __dirname , "./src/hooks" ),
"@store" : path . resolve ( __dirname , "./src/store" ),
"@services" : path . resolve ( __dirname , "./src/services" ),
"@constants" : path . resolve ( __dirname , "./src/constants" ),
"@data" : path . resolve ( __dirname , "./src/data" ),
"@styles" : path . resolve ( __dirname , "./src/styles" ),
"@icons" : path . resolve ( __dirname , "./src/ui/icons" ),
"@assets" : path . resolve ( __dirname , "./src/assets" )
}
Architecture Diagram
Component Architecture
Data Flow
User Interaction
User interacts with a page component (e.g., Sales.tsx)
Action Dispatch
Page dispatches a Redux action (e.g., addSaleRequest)
Reducer Update
Redux slice reducer updates the state synchronously
Saga Side Effect
Redux Saga intercepts the action and handles async operations
Persistence
Redux Persist automatically saves state changes to IndexedDB via LocalForage
UI Update
React components re-render with updated state from the store
Example Flow: Creating a Sale
// 1. User submits sale form in Sales.tsx
dispatch ( addSaleRequest ({
id: 'sale-123' ,
clienteId: 'client-456' ,
montoTotal: 1500
}));
// 2. salesSlice reducer adds sale with PENDING status
state . items . push ({ ... payload , sync_status: 'PENDING' });
// 3. rootSaga intercepts and attempts sync if online
function* handleAddSale ( action ) {
if ( navigator . onLine ) {
yield delay ( 500 );
yield put ( addSaleSuccess ( action . payload . id ));
}
}
// 4. Redux Persist saves to IndexedDB automatically
// 5. Components re-render with updated sale list
PWA Configuration
The application is configured as a Progressive Web App in vite.config.ts:11-26:
VitePWA ({
registerType: "autoUpdate" ,
includeAssets: [ "favicon.ico" , "apple-touch-icon.png" , "mask-icon.svg" ],
manifest: {
name: "Sistema de Gestión de Flotas SUNAT 2026" ,
short_name: "FleetSUNAT" ,
description: "Gestión logística y facturación electrónica offline-first" ,
theme_color: "#ffffff" ,
background_color: "#ffffff" ,
display: "standalone" ,
icons: [
{ src: "pwa-192x192.png" , sizes: "192x192" , type: "image/png" },
{ src: "pwa-512x512.png" , sizes: "512x512" , type: "image/png" }
]
}
})
The PWA manifest defines “FleetSUNAT” as the application name, optimized for Peruvian SUNAT (tax authority) electronic billing compliance.
Key Features
Offline-First Architecture
All critical data is persisted locally using IndexedDB through LocalForage. Users can create sales, manage fleet data, and access information without internet connectivity.
Automatic Synchronization
When the application reconnects to the internet, pending operations are automatically synchronized to the backend via Redux Saga.
Full TypeScript implementation ensures type safety across components, reducers, and sagas, reducing runtime errors.
Path-Based Code Splitting
React Router enables automatic code splitting, loading only the JavaScript needed for the current route.
Build and Deployment
The application uses Vite for optimized production builds:
# Development server
npm run dev
# Production build with TypeScript checking
npm run build
# Preview production build
npm run preview
Always run tsc -b before building to catch TypeScript errors early. The build script includes this step automatically.
Next Steps
Offline Sync Learn about the offline-first architecture and sync patterns
State Management Deep dive into Redux Toolkit and Redux Saga implementation