Overview
The RTO Profit Simulator uses a combination of default values, localStorage persistence, and environment-aware configuration. This page documents all configurable aspects of the application.
Default Business Values
The application initializes with realistic default values defined in src/App.jsx:
const defaultData = {
monthlyOrders: 10000,
averageOrderValue: 1500,
codPercentage: 60,
rtoPercentage: 30,
forwardShippingCost: 60,
returnShippingCost: 60,
productCost: 500,
}
Default Values Explained
Total number of orders processed per monthTypical range: 1,000 - 100,000 depending on business size
Average value per order in Indian Rupees (₹)Typical range: ₹500 - ₹5,000 for e-commerce businesses
Percentage of orders that are Cash on Delivery (0-100)Industry benchmark: 40-70% for Indian e-commerce
Percentage of COD orders that result in Return to Origin (0-100)Industry benchmark:
- Healthy: < 15%
- Moderate: 15-25%
- High: 25-35%
- Critical: > 35%
Cost of shipping an order to the customer (₹)Typical range: ₹40 - ₹150 depending on weight and distance
Cost of shipping an RTO order back to warehouse (₹)Usually equal to: Forward shipping cost
Cost of goods sold per order (₹)Typical range: 30-60% of average order value
LocalStorage Persistence
The application automatically saves user inputs and preferences to browser localStorage.
Data Persistence
Storage Key: rtoSimulatorData
Implementation:
// Initialize from localStorage
const [data, setData] = useState(() => {
const saved = localStorage.getItem('rtoSimulatorData')
if (saved) {
try {
return JSON.parse(saved)
} catch (e) {
console.error("Failed to parse local storage data", e)
}
}
return defaultData
})
// Save to localStorage on every change
useEffect(() => {
localStorage.setItem('rtoSimulatorData', JSON.stringify(data))
}, [data])
Stored Data Structure:
{
"monthlyOrders": 10000,
"averageOrderValue": 1500,
"codPercentage": 60,
"rtoPercentage": 30,
"forwardShippingCost": 60,
"returnShippingCost": 60,
"productCost": 500
}
Features
- Values persist across browser sessions
- Automatic fallback to defaults if parsing fails
- Reset functionality restores defaults
- Data is user-specific per browser/device
Clearing Persisted Data
Via Reset Button:
const handleReset = () => {
setData(defaultData)
}
Via Browser Console:
localStorage.removeItem('rtoSimulatorData')
location.reload()
Clear All Application Data:
localStorage.clear()
location.reload()
Dark Mode Configuration
The application supports light and dark themes with localStorage persistence.
Theme Persistence
Storage Key: rtoSimulatorTheme
Implementation:
// Initialize theme from localStorage
const [darkMode, setDarkMode] = useState(() => {
return localStorage.getItem('rtoSimulatorTheme') === 'dark'
})
// Apply theme to DOM
useEffect(() => {
if (darkMode) {
document.body.setAttribute('data-theme', 'dark')
localStorage.setItem('rtoSimulatorTheme', 'dark')
} else {
document.body.removeAttribute('data-theme')
localStorage.setItem('rtoSimulatorTheme', 'light')
}
}, [darkMode])
Theme Toggle
UI Component:
<button onClick={() => setDarkMode(!darkMode)} className="icon-btn">
{darkMode ? <Sun size={20} /> : <Moon size={20} />}
</button>
Theme Variables
Theme colors are controlled via CSS custom properties that change based on [data-theme="dark"] attribute:
Light Theme (Default):
:root {
--primary-blue: #2563eb;
--success: #10b981;
--warning: #f59e0b;
--danger: #ef4444;
--text-primary: #1e293b;
--text-secondary: #64748b;
--surface-white: #ffffff;
--background: #f8fafc;
--border-color: #e2e8f0;
}
Dark Theme:
[data-theme="dark"] {
--text-primary: #f1f5f9;
--text-secondary: #cbd5e1;
--surface-white: #1e293b;
--background: #0f172a;
--border-color: #334155;
}
Build Configuration
The application uses Vite as the build tool.
Vite Configuration
File: vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
})
Build Commands
Development Server:
npm run dev
# Starts at http://localhost:5173
Production Build:
npm run build
# Outputs to /dist directory
Preview Production Build:
Build Output
- Output Directory:
dist/
- Asset Optimization: Minified JS, CSS, and images
- Code Splitting: Automatic vendor chunking
- Browser Support: Modern browsers (ES2015+)
Environment Variables
The application currently does not use environment variables. All configuration is hardcoded or stored in localStorage.
Adding Environment Variables
If you need to add environment variables (e.g., for API keys or feature flags):
1. Create .env file:
VITE_APP_TITLE=RTO Profit Simulator
VITE_API_ENDPOINT=https://api.example.com
2. Access in code:
const appTitle = import.meta.env.VITE_APP_TITLE
const apiEndpoint = import.meta.env.VITE_API_ENDPOINT
3. TypeScript types (optional):
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_API_ENDPOINT: string
}
View Mode State
The application supports toggling between monthly and annual projections.
Implementation
const [isAnnual, setIsAnnual] = useState(false)
Toggle UI:
<button
className={`toggle-btn ${!isAnnual ? 'active' : ''}`}
onClick={() => setIsAnnual(false)}
>
Monthly View
</button>
<button
className={`toggle-btn ${isAnnual ? 'active' : ''}`}
onClick={() => setIsAnnual(true)}
>
Annual Projection
</button>
Effect on Calculations:
const metrics = calculateMetrics(data, isAnnual)
// When isAnnual is true, all values are multiplied by 12
PDF Export Configuration
The application supports exporting reports to PDF using jsPDF and jspdf-autotable.
Export Settings
const exportToPDF = () => {
const pdf = new jsPDF('p', 'pt', 'a4')
const margin = 40
// Configure tables
autoTable(pdf, {
theme: 'grid',
headStyles: { fillColor: [37, 99, 235] }, // Primary blue
})
// Save file
pdf.save(`RTO-Simulator-Report-${isAnnual ? 'Annual' : 'Monthly'}.pdf`)
}
PDF Content
- Header: Title and export timestamp
- Table 1: Business Inputs
- Table 2: Financial Impact Overview
- Table 3: Optimization Projections (5%, 10%, 15% reduction)
- Footer: Disclaimer text
Customization Options
Change PDF Colors:
headStyles: {
fillColor: [37, 99, 235], // RGB for blue header
textColor: [255, 255, 255] // RGB for white text
}
Change Page Format:
const pdf = new jsPDF('l', 'pt', 'letter') // Landscape, letter size
Add Logo or Branding:
pdf.addImage(logoBase64, 'PNG', margin, margin, 100, 50)
Customization Guide
Changing Default Values
Location: src/App.jsx:14-22
const defaultData = {
monthlyOrders: 5000, // Change to your typical order volume
averageOrderValue: 2000, // Adjust to your AOV
codPercentage: 50, // Your COD percentage
// ... other values
}
Adjusting Risk Thresholds
Location: src/components/RiskMeter.jsx:4-9
const getRiskLevel = (rto) => {
if (rto <= 10) return { /* Healthy */ }
if (rto <= 20) return { /* Moderate */ }
if (rto <= 30) return { /* High */ }
return { /* Critical */ }
}
Modifying Insight Logic
Location: src/components/AIInsights.jsx:14-66
// Add new insight condition
if (data.monthlyOrders > 50000) {
insights.push({
type: 'opportunity',
icon: <TrendingUp />,
title: 'High Volume Business',
message: 'Consider enterprise logistics solutions...'
})
}
Changing Currency and Locale
Current: Indian Rupees (₹) with en-IN locale
To Change:
// Replace all instances of:
const formatCurrency = (value) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0
}).format(value)
}
Animation Durations
CountUp Animation:
<CountUp end={value} duration={1.5} separator="," decimals={0} />
Chart Transitions:
transition: stroke-dasharray 1s ease-out, stroke 1s ease-out;
Optimization Tips
- Memoize Expensive Calculations:
const metrics = useMemo(() => calculateMetrics(data, isAnnual), [data, isAnnual])
- Debounce Input Changes:
const debouncedChange = useMemo(
() => debounce(handleDataChange, 300),
[]
)
- Lazy Load Charts:
const VisualAnalytics = lazy(() => import('./components/VisualAnalytics'))
Browser Compatibility
Supported Browsers
- Chrome/Edge: Latest 2 versions
- Firefox: Latest 2 versions
- Safari: Latest 2 versions
- Mobile browsers: iOS Safari 12+, Chrome Android 90+
Required Features
- ES2015+ JavaScript
- CSS Custom Properties
- LocalStorage API
- Canvas API (for charts)
Polyfills
No polyfills are currently included. For broader support, consider adding:
import 'core-js/stable'
import 'regenerator-runtime/runtime'
Deployment Configuration
Static Site Deployment
Vercel/Netlify:
- Build command:
npm run build
- Publish directory:
dist
- Node version: 18.x or higher
Nginx Configuration:
location / {
try_files $uri $uri/ /index.html;
}
Apache Configuration:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
Base Path Configuration
If deploying to a subdirectory:
// vite.config.js
export default defineConfig({
base: '/rto-simulator/',
plugins: [react()],
})