diff --git "a/frontend/src/App.jsx" "b/frontend/src/App.jsx"
--- "a/frontend/src/App.jsx"
+++ "b/frontend/src/App.jsx"
@@ -1,2266 +1,29 @@
-import React, { useState, useEffect, useRef, useCallback } from 'react';
-import { motion, AnimatePresence } from 'framer-motion';
-import * as API from './api.js';
-import {
- Shield, X, CreditCard, Wallet, Smartphone, Activity, Settings,
- MapPin, ChevronDown, Search, MessageSquare, Award,
- Zap, ShoppingBasket, ShoppingCart, User, Check, Plus,
- RotateCcw, Info, CheckCircle, Star, Sparkles, Flame, CalendarDays,
- ShieldCheck, HelpCircle, TrendingUp, AlertTriangle, Play
-} from 'lucide-react';
-import { AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
-import confetti from 'canvas-confetti';
-import './App.css';
-
-// Import Modular Components
-import AuthPortal from './components/AuthPortal.jsx';
-import DiscoveryHub from './components/DiscoveryHub.jsx';
-import RestaurantDetail from './components/RestaurantDetail.jsx';
-import CartCheckout from './components/CartCheckout.jsx';
-import RealTimeTracking from './components/RealTimeTracking.jsx';
-import AICommerceAgent from './components/AICommerceAgent.jsx';
-import OpsControlPanel from './components/OpsControlPanel.jsx';
-import LockScreen from './components/LockScreen.jsx';
-import LoyaltyAnalytics from './components/LoyaltyAnalytics.jsx';
-
-// Import New Admin & Support Components
-import MerchantStockAdmin from './components/MerchantStockAdmin.jsx';
-import FleetLogisticsAdmin from './components/FleetLogisticsAdmin.jsx';
-import FinancialOpsAdmin from './components/FinancialOpsAdmin.jsx';
-import GrowthAnalyticsAdmin from './components/GrowthAnalyticsAdmin.jsx';
-
-// Import HyperFlow 4.0 Module Views
-import DemandOracleView from './components/DemandOracleView.jsx';
-import ETATruthView from './components/ETATruthView.jsx';
-import RefundOracleView from './components/RefundOracleView.jsx';
-import DineoutSniperView from './components/DineoutSniperView.jsx';
-import DispatchMapView from './components/DispatchMapView.jsx';
-
-import RefundStatus from './components/RefundStatus.jsx';
-import HelpSupport from './components/HelpSupport.jsx';
-import ChatbotHelp from './components/ChatbotHelp.jsx';
-import FestivalThemeManager from './components/FestivalThemeManager.jsx';
-
-// Real coordinates in Bhubaneswar (Patia / Prasanti Vihar area)
-const HUB_COORDINATES = {
- Bhubaneswar: {
- center: [20.3533, 85.8333],
- route: [
- [20.3533, 85.8333], // Swiggy Instamart Warehouse (Patia)
- [20.3562, 85.8315], // Prasanti Vihar road
- [20.3585, 85.8288], // Near Lp 60
- [20.3601, 85.8272] // Gaurav Home
- ]
- }
-};
-
-const getInterpolatedPosition = (route, progress) => {
- if (!route || route.length === 0) return null;
- if (route.length === 1) return route[0];
- const totalSegments = route.length - 1;
- const progressPercent = progress / 100;
- const segmentIndex = Math.min(
- Math.floor(progressPercent * totalSegments),
- totalSegments - 1
- );
- const start = route[segmentIndex];
- const end = route[segmentIndex + 1];
- const segmentProgress = (progressPercent * totalSegments) - segmentIndex;
- const lat = start[0] + (end[0] - start[0]) * segmentProgress;
- const lng = start[1] + (end[1] - start[1]) * segmentProgress;
- return [lat, lng];
-};
-
-function LeafletMap({ center, routePoints, riderPos, theme, zoom = 14 }) {
- const mapRef = useRef(null);
- const mapInstanceRef = useRef(null);
- const routeLayerRef = useRef(null);
- const riderMarkerRef = useRef(null);
- const storeMarkerRef = useRef(null);
- const customerMarkersRef = useRef([]);
-
- useEffect(() => {
- if (!mapRef.current || !window.L) return;
-
- const map = window.L.map(mapRef.current, {
- zoomControl: false,
- attributionControl: false
- }).setView(center, zoom);
-
- mapInstanceRef.current = map;
-
- const darkTiles = 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png';
- const lightTiles = 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png';
-
- window.L.tileLayer(theme === 'dark' ? darkTiles : lightTiles, {
- maxZoom: 19
- }).addTo(map);
-
- return () => {
- map.remove();
- mapInstanceRef.current = null;
- };
- }, []);
-
- useEffect(() => {
- const map = mapInstanceRef.current;
- if (!map || !window.L) return;
-
- map.eachLayer((layer) => {
- if (layer instanceof window.L.TileLayer) {
- map.removeLayer(layer);
- }
- });
-
- const darkTiles = 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png';
- const lightTiles = 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png';
-
- window.L.tileLayer(theme === 'dark' ? darkTiles : lightTiles, {
- maxZoom: 19
- }).addTo(map);
- }, [theme]);
-
- useEffect(() => {
- const map = mapInstanceRef.current;
- if (map) {
- map.setView(center, zoom);
- }
- }, [center, zoom]);
-
- useEffect(() => {
- const map = mapInstanceRef.current;
- if (!map || !window.L) return;
-
- if (routeLayerRef.current) {
- map.removeLayer(routeLayerRef.current);
- }
-
- if (routePoints && routePoints.length > 0) {
- routeLayerRef.current = window.L.polyline(routePoints, {
- color: '#6C63FF',
- weight: 5,
- dashArray: '8, 8',
- opacity: 0.95
- }).addTo(map);
- }
-
- if (storeMarkerRef.current) map.removeLayer(storeMarkerRef.current);
- if (riderMarkerRef.current) map.removeLayer(riderMarkerRef.current);
- customerMarkersRef.current.forEach(m => map.removeLayer(m));
- customerMarkersRef.current = [];
-
- const createCircleIcon = (color, size, pulse = false) => {
- return window.L.divIcon({
- className: 'custom-map-pin',
- html: `
`,
- iconSize: [size, size],
- iconAnchor: [size/2, size/2]
- });
- };
-
- if (routePoints && routePoints.length > 0) {
- storeMarkerRef.current = window.L.marker(routePoints[0], {
- icon: createCircleIcon('#6C63FF', 14)
- }).addTo(map);
-
- const lastPoint = routePoints[routePoints.length - 1];
- const marker = window.L.marker(lastPoint, {
- icon: createCircleIcon('#00D4AA', 14)
- }).addTo(map);
- customerMarkersRef.current.push(marker);
- }
-
- if (riderPos) {
- riderMarkerRef.current = window.L.marker(riderPos, {
- icon: createCircleIcon('#FF4757', 18, true)
- }).addTo(map);
- }
-
- }, [routePoints, riderPos]);
-
- return
;
-}
-
-function CategoryIcon({ name, className }) {
- if (name === "Biryani") {
- return (
-
-
-
-
-
-
-
- );
- }
- if (name === "Pizzas") {
- return (
-
-
-
-
-
-
-
- );
- }
- if (name === "North Indian") {
- return (
-
-
-
-
-
-
- );
- }
- if (name === "Healthy") {
- return (
-
-
-
-
- );
- }
- if (name === "Groceries") {
- return (
-
-
-
-
- );
- }
- return null;
-}
-
-const promoBanners = [
- { title: "Diwali Special: Up to 50% Off", desc: "Celebrate with royal Biryani from Behrouz & more partners", color: "from-[#FFB347] to-[#FF4757]", badge: "Festive" },
- { title: "9-Min Groceries Delivery", desc: "Get fresh milk, vegetables, and essentials instantly", color: "from-[#6C63FF] to-[#A078FF]", badge: "Quick" },
- { title: "Dineout Slot Bookings Open", desc: "Book dining slots at Mayfair Lagoon & premium buffets", color: "from-[#00D4AA] to-[#6C63FF]", badge: "Dineout" }
-];
-
-const categories = [
- { name: "Biryani" },
- { name: "Pizzas" },
- { name: "North Indian" },
- { name: "Healthy" },
- { name: "Groceries" }
-];
+import React from 'react';
+import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
+import Sidebar from './components/Sidebar.jsx';
+import AIAgent from './pages/AIAgent.jsx';
+import DarkStoreIntel from './pages/DarkStoreIntel.jsx';
+import RouteIntelligence from './pages/RouteIntelligence.jsx';
+import MLGuard from './pages/MLGuard.jsx';
+import Analytics from './pages/Analytics.jsx';
+import './index.css';
export default function App() {
- const [isLoggedIn, setIsLoggedIn] = useState(() => !!localStorage.getItem('swiggy_access_token'));
- const [activeTab, setActiveTab] = useState('home');
- const [appView, setAppView] = useState('consumer');
- const [isSimulatorMode, setIsSimulatorMode] = useState(window.innerWidth >= 1024);
- const [isMobileDevice, setIsMobileDevice] = useState(window.innerWidth < 1024);
- const [donateClimate, setDonateClimate] = useState(true);
- const [donateFoodSafety, setDonateFoodSafety] = useState(true);
- const [showSplash, setShowSplash] = useState(false);
- const [showLockScreen, setShowLockScreen] = useState(false);
-
- useEffect(() => {
- const handleResize = () => {
- const isMobile = window.innerWidth < 1024;
- setIsMobileDevice(isMobile);
- if (isMobile) {
- setIsSimulatorMode(true);
- }
- };
- window.addEventListener('resize', handleResize);
- // run initial check
- handleResize();
- return () => window.removeEventListener('resize', handleResize);
- }, []);
-
- useEffect(() => {
- if (showSplash) {
- const timer = setTimeout(() => {
- setShowSplash(false);
- }, 2200); // 2.2 seconds splash animation
- return () => clearTimeout(timer);
- }
- }, [showSplash]);
-
- // Swiggy, Zomato, Blinkit Operations & SOP states
- const [adminSubTab, setAdminSubTab] = useState('system'); // 'system', 'restaurant', 'picking', 'logistics'
- const [restaurantOrders, setRestaurantOrders] = useState([
- { id: "O-8374", name: "Anjali Patnaik", items: "1x Dum Gosht Biryani", elapsed: 0, status: "PENDING", limit: 45, price: 349 },
- { id: "O-2938", name: "Siddharth Sen", items: "2x Butter Chicken, 1x Paneer Tikka", elapsed: 0, status: "PENDING", limit: 45, price: 770 },
- ]);
- const [pickingList, setPickingList] = useState([
- { id: "g_milk", name: "Amul Taaza Milk (1L)", qty: 2, location: "Aisle 2, A1", status: "PENDING" },
- { id: "g_tomatoes", name: "Fresh Tomatoes (500g)", qty: 1, location: "Aisle 5, C3", status: "PENDING" },
- { id: "g_bananas", name: "Organic Bananas (1 doz)", qty: 1, location: "Aisle 1, B2", status: "PENDING" }
- ]);
- const [pickingSLA, setPickingSLA] = useState(0);
- const [pickingActive, setPickingActive] = useState(true);
- const [riderList, setRiderList] = useState([
- { id: "R-01", name: "Sourav M.", status: "IDLE", location: "Patia Hub", batchedOrders: [] },
- { id: "R-02", name: "Amit K.", status: "DELIVERING", location: "Prasanti Vihar Rd", batchedOrders: ["O-8374"] },
- { id: "R-03", name: "Ranjan D.", status: "DELIVERING", location: "Lp 60 Lane", batchedOrders: ["O-2938"] }
- ]);
- const [rainIncentive, setRainIncentive] = useState(false);
-
- // Operational Simulation Timers
- useEffect(() => {
- const interval = setInterval(() => {
- // 1. Restaurant SLA order timer
- setRestaurantOrders(prev => prev.map(order => {
- if (order.status === "PENDING") {
- const nextElapsed = order.elapsed + 1;
- if (nextElapsed >= order.limit) {
- return { ...order, elapsed: order.limit, status: "TIMEOUT (Lapsed)" };
- }
- return { ...order, elapsed: nextElapsed };
- }
- return order;
- }));
-
- // 2. Picking SLA timer
- setPickingSLA(prev => {
- if (pickingActive) return prev + 1;
- return prev;
- });
- }, 1000);
- return () => clearInterval(interval);
- }, [pickingActive]);
-
- const savedAddresses = [
- { id: "187465656", tag: "Home", name: "Gaurav Nayak", detail: "Plot Lp 60, Prasanti Vihar, Patia, Bhubaneswar, 751024" },
- { id: "d7n8j7j5p2h33j28em90", tag: "Work", name: "Gaurav Nayak", detail: "In front of Swiggy Instamart Warehouse, Patia, Bhubaneswar" },
- { id: "252492248", tag: "Other", name: "Gaurav Nayak", detail: "Lp 60, Prasanti Vihar, Patia, Bhubaneswar" }
- ];
- const [selectedAddress, setSelectedAddress] = useState(savedAddresses[0]);
- const [addressDropdownOpen, setAddressDropdownOpen] = useState(false);
-
- // Cart & Orders State
- const [cart, setCart] = useState([]);
- const [customizingItem, setCustomizingItem] = useState(null);
- const [selectedBeverage, setSelectedBeverage] = useState('raita'); // 'raita' or 'pepsi'
- const [selectedSweet, setSelectedSweet] = useState('jamun'); // 'jamun', 'meetha', or 'none'
- const [deliveryMode, setDeliveryMode] = useState('ev'); // 'ev' or 'normal'
- const [activeOrder, setActiveOrder] = useState(null);
- const [riderProgress, setRiderProgress] = useState(0);
- const [restaurantPageOpen, setRestaurantPageOpen] = useState(false);
- const [selectedRestaurant, setSelectedRestaurant] = useState(null);
-
- const handleSelectRestaurant = (rest) => {
- setSelectedRestaurant(rest);
- setRestaurantPageOpen(true);
- if (!rest.menu || rest.menu.length === 0) {
- API.fetchRestaurantMenu(rest.id).then(menuData => {
- if (menuData && Array.isArray(menuData) && menuData.length > 0) {
- setRestaurants(prev => prev.map(r => r.id === rest.id ? { ...r, menu: menuData } : r));
- setSelectedRestaurant(prev => prev && prev.id === rest.id ? { ...prev, menu: menuData } : prev);
- }
- });
- }
- };
-
- // Search state
- const [searchQuery, setSearchQuery] = useState("");
- const [vegOnly, setVegOnly] = useState(false);
- const [selectedCuisine, setSelectedCuisine] = useState(null);
-
- // AI Agent Chat States
- const [chatOpen, setChatOpen] = useState(false);
- const [chatMessages, setChatMessages] = useState([
- { sender: 'agent', text: 'Hey Gaurav! I can query restaurants and groceries using Swiggy tools. Tell me your dietary goals or cravings.', time: '9:15pm', tools: [] }
- ]);
- const [chatInput, setChatInput] = useState("");
- const [isAgentThinking, setIsAgentThinking] = useState(false);
- const [agentThinkingTools, setAgentThinkingTools] = useState([]);
-
- // Telemetry & Anomaly parameters
- const [censoringRate, setCensoringRate] = useState(0.40);
- const [forecastOutput, setForecastOutput] = useState({
- censoring_rate: 0.40,
- ols_wmape: 0.208,
- tobit_wmape: 0.139,
- lift_pct: 33.1,
- converged: true
- });
- const [stormSurge, setStormSurge] = useState(false);
- const [driftInjected, setDriftInjected] = useState(false);
- const [arbitrageMessage, setArbitrageMessage] = useState("");
- const [rescueOffers, setRescueOffers] = useState([]);
- const [rescueTimer, setRescueTimer] = useState(299);
- const [securityLogs, setSecurityLogs] = useState([
- { time: "14:10:02", event: "SYSTEM BOOT SEQUENCE INITIATED...", type: "info" },
- { time: "14:10:12", event: "Anti-Arbitrage Guard active on Patia subnets.", type: "success" }
- ]);
- const [activeGroceryForecast, setActiveGroceryForecast] = useState(null);
-
- // Payment Gateway States
- const [paymentScreenOpen, setPaymentScreenOpen] = useState(false);
- const [selectedPaymentMethod, setSelectedPaymentMethod] = useState("cobranded");
- const [paymentProcessing, setPaymentProcessing] = useState(false);
- const [paymentSuccess, setPaymentSuccess] = useState(false);
- const [checkoutPayload, setCheckoutPayload] = useState(null);
- const [backendUrl] = useState(import.meta.env.VITE_BACKEND_URL || "http://localhost:7860");
- const [theme, setTheme] = useState('dark');
-
- // Customer Loyalty & Retention Metrics States
- const [isPro, setIsPro] = useState(false); // HyperFlow Pro membership
- const [streakOrders, setStreakOrders] = useState(1); // Gamified progress
- const [lastOrderedItem, setLastOrderedItem] = useState({
- id: "dum_gosht",
- name: "Dum Gosht Biryani",
- price: 349,
- restaurantName: "Behrouz Biryani",
- restaurantId: "rest_behrouz",
- protein: 36,
- calories: 540
- });
-
- // Festive theme overrides
- const [festivalTheme, setFestivalTheme] = useState('nominal'); // 'nominal', 'diwali', 'holi'
-
- // Coupons database
- const [coupons, setCoupons] = useState([
- { code: "HYPERPRO", pct: 15, minOrder: 300, desc: "15% off above ₹300" },
- { code: "DIWALI50", pct: 50, minOrder: 500, desc: "Festive 50% off above ₹500" },
- { code: "FREEFEES", pct: 100, minOrder: 0, desc: "Zero delivery fees coupon" }
- ]);
- const [appliedCoupon, setAppliedCoupon] = useState(null);
- const [couponCodeInput, setCouponCodeInput] = useState("");
- const [couponMessage, setCouponMessage] = useState("");
-
- // Expense Logs database
- const [expenseLogs, setExpenseLogs] = useState([
- { id: 1, name: "July 04", amount: 480, calories: 1250 },
- { id: 2, name: "July 05", amount: 620, calories: 1800 },
- { id: 3, name: "July 06", amount: 290, calories: 950 },
- { id: 4, name: "July 07", amount: 840, calories: 2100 },
- { id: 5, name: "July 08", amount: 350, calories: 1100 }
- ]);
-
- // Dineout slots reservation database
- const [reservations, setReservations] = useState([
- { id: "res_101", hotel: "Mayfair Lagoon", time: "08:30 PM", party: 2, status: "CONFIRMED" }
- ]);
-
- // Dynamic Databases
- const [restaurants, setRestaurants] = useState([
- {
- id: "rest_behrouz",
- name: "Behrouz Biryani",
- cuisine: "Biryani · Mughlai · Royal",
- rating: 4.6,
- distance: "2.1 km",
- time: "28 min",
- slaConfidence: 97,
- isAIPick: true,
- isExclusive: true,
- image: "https://lh3.googleusercontent.com/aida-public/AB6AXuB3O6h3kN5v2ZfZDd3Ufds1_PUUHBmlla4WShhsUOwN1BiWVty9aGs9k-ujSiY3HWg0c-a6yUVCpufZJTK3hqLopqOy-INM9HYG-SKcVE0PbA__mUudSLa2FZF4yeu1q6fwxpjVZXn7yNLyelP_KZmven-uKjmR8Q3bG2PkZi64JiSya_N0Zb1Ww0kf3A7LW34llf4b4dpiTff9GbejYkJFooJR4Slc4fs85sLnGz-kZjWnuFABxdtocK8oviRGW5vmkB6XF1IMU4YS",
- menu: [
- { id: "dum_gosht", name: "Dum Gosht Biryani", price: 349, rating: 4.6, desc: "Fragrant long-grain basmati rice layered with juicy mutton in royal spices.", protein: 36, cal: 540, veg: false, image: "https://lh3.googleusercontent.com/aida-public/AB6AXuAy8Ulq_axTRp6t2EagRb5G-YtqpRnvPzPmyNLG-1FBJ0_p-83Hb7anlB2ZhXsi9Yd0x4n4HVmWhRYJ4r1J0aeYhAKyBpAHs5R59gryk1trq626wW1LuUFZ7SkM8OvhMdS78RXzvNqpn-E03C047MfVamHP-NIetglvLA2A5zzJjsUUJ8KlWdV_E4DdUow8sK7YValAPmnwch_EcyAii9s8yhA-yi925HvzzqKBSoWyYDzGpNFU46e2dbF68cDx_CA1jI2gcAKBGs_E" },
- { id: "lazeez_chicken", name: "Lazeez Bhuna Murgh Biryani", price: 299, rating: 4.5, desc: "Tender boneless chicken in bhuna spices layered with basmati rice.", protein: 32, cal: 480, veg: false, image: "https://lh3.googleusercontent.com/aida-public/AB6AXuBVH7_iiDjEwAqM-iOH8jm3r4ljZMINGVU_Xp5Q-c5wjp04ir3wyacHOLYmjmdPdsAEKmN7NFvNQ8ccPIwOAUEqVu7ESWWZFV7ECSWX7JzlbDWyCtYJ_7mti2MWNy3Yuj77gJG8cjX2qVom1OGcFA8kzAFxQ4u3CBk-mzNORIV01WqDHbcX9ae4xKUwXCM69aXnh0vKIHvWcTm7xzkbIx4a_pAK1gBNf1lGPPzRLuDKikphdzej965g0gpkdAKQ1V-5hDx9OoV1vQMF" },
- { id: "mint_raita", name: "Mint Raita", price: 49, rating: 4.2, desc: "Refreshing raita flavored with fresh mint leaves.", protein: 2, cal: 60, veg: true, image: "https://lh3.googleusercontent.com/aida-public/AB6AXuA9dB7F5xSnF4KMn9vZmYR-rdDJJynymGxYucwoE-YBitPw0VKGSu-DN14kA90BSzp-2uy6VqlvfPFGUv1w1bAkAncDACJEjmjyIs5U_edIxKkwyJXxKBdiWMNunXofnk0gpGuMhOYRmiAlpBLt1eDqi27iQu4sKk2m2BOZdHLrGxGFXuHSxNxRfZrvdjjDlDh9Qzm9Bq8gJA1kCDLJqJ4Wt4tvK3bGLCdxh0ENy_AR1ED6oHIrCU53WfftTybXUz_QCYlouZZvj1fU" }
- ]
- },
- {
- id: "rest_carbon_grill",
- name: "Carbon Grill",
- cuisine: "Burgers · Wings · Sides",
- rating: 4.3,
- distance: "1.4 km",
- time: "22 min",
- slaConfidence: 94,
- isAIPick: false,
- isExclusive: false,
- image: "https://lh3.googleusercontent.com/aida-public/AB6AXuD9C62CkwFO1Ta65rOPGt_zkQb3NWBfpIVfhSCWsS173P7Hw1t8O2CFnA1Swhsh03BFAJeCU4v8zMcs2FtgfS9UKrkQ-pgIxmQV0atKwEY1VvIrOO2nqjJirHB5LtlEy7v2E23zmpz5QUROCmGsEwpUTOxc6-W7bqEnwZTpjlEj84W0_wRNkm3oiChRsbQBbdUsj6iQ4IQ8MjgCXDjvXHjIGyb2EehurUmG2rcFE5E_2NQqMXhnC7sZPl5JUl0b-89s8s1A5HghkpjV",
- menu: [
- { id: "truffle_burger", name: "Truffle Cheese Burger", price: 280, rating: 4.5, desc: "Gourmet double-patty burger with Swiss cheese and black truffle aioli.", protein: 34, cal: 620, veg: false, image: "https://lh3.googleusercontent.com/aida-public/AB6AXuD9C62CkwFO1Ta65rOPGt_zkQb3NWBfpIVfhSCWsS173P7Hw1t8O2CFnA1Swhsh03BFAJeCU4v8zMcs2FtgfS9UKrkQ-pgIxmQV0atKwEY1VvIrOO2nqjJirHB5LtlEy7v2E23zmpz5QUROCmGsEwpUTOxc6-W7bqEnwZTpjlEj84W0_wRNkm3oiChRsbQBbdUsj6iQ4IQ8MjgCXDjvXHjIGyb2EehurUmG2rcFE5E_2NQqMXhnC7sZPl5JUl0b-89s8s1A5HghkpjV" },
- { id: "peri_fries", name: "Spicy Peri Peri Fries", price: 149, rating: 4.3, desc: "Crispy golden skin-on fries tossed in house peri-peri spice dust.", protein: 5, cal: 320, veg: true, image: "https://lh3.googleusercontent.com/aida-public/AB6AXuD9C62CkwFO1Ta65rOPGt_zkQb3NWBfpIVfhSCWsS173P7Hw1t8O2CFnA1Swhsh03BFAJeCU4v8zMcs2FtgfS9UKrkQ-pgIxmQV0atKwEY1VvIrOO2nqjJirHB5LtlEy7v2E23zmpz5QUROCmGsEwpUTOxc6-W7bqEnwZTpjlEj84W0_wRNkm3oiChRsbQBbdUsj6iQ4IQ8MjgCXDjvXHjIGyb2EehurUmG2rcFE5E_2NQqMXhnC7sZPl5JUl0b-89s8s1A5HghkpjV" }
- ]
- },
- {
- id: "rest_yoko_ono",
- name: "Yoko Ono Sushi",
- cuisine: "Sushi · Asian · Japanese",
- rating: 4.4,
- distance: "3.2 km",
- time: "18 min",
- slaConfidence: 98,
- isAIPick: false,
- isExclusive: true,
- image: "https://lh3.googleusercontent.com/aida-public/AB6AXuCBY63vuIkeBp6l5cHYDUYAUxyfZjekeIUDrgoaWXdYWfRsIItON9yVcNgasVY5EVJ_z9UCEYE7ifS6es_em8GXuQSZjL4elMAOcYKY-mFqvK7XoIYiCdoO9fXcs76s27BFjIlZ-jibt94sXMKAMiW-HDhL8Fx6YgFDMjXCKJuqgQvL6f2QokApfLDSvnpgf5uRCpVCyjlevWvENzKb2pD1gJvWBrOj_kU8HsHYg8siO1GP2yGFdEgOS79jFlelYdFjbEs_cIizY-X6",
- menu: [
- { id: "salmon_nigiri", name: "Salmon Nigiri (2pcs)", price: 320, rating: 4.7, desc: "Slices of premium fresh Atlantic salmon laid over seasoned sushi rice.", protein: 14, cal: 180, veg: false, image: "https://lh3.googleusercontent.com/aida-public/AB6AXuCBY63vuIkeBp6l5cHYDUYAUxyfZjekeIUDrgoaWXdYWfRsIItON9yVcNgasVY5EVJ_z9UCEYE7ifS6es_em8GXuQSZjL4elMAOcYKY-mFqvK7XoIYiCdoO9fXcs76s27BFjIlZ-jibt94sXMKAMiW-HDhL8Fx6YgFDMjXCKJuqgQvL6f2QokApfLDSvnpgf5uRCpVCyjlevWvENzKb2pD1gJvWBrOj_kU8HsHYg8siO1GP2yGFdEgOS79jFlelYdFjbEs_cIizY-X6" },
- { id: "tuna_maki", name: "Tuna Maki Roll (6pcs)", price: 280, rating: 4.5, desc: "Yellowfin tuna wrapped in nori sheet with sushi rice.", protein: 18, cal: 220, veg: false, image: "https://lh3.googleusercontent.com/aida-public/AB6AXuCBY63vuIkeBp6l5cHYDUYAUxyfZjekeIUDrgoaWXdYWfRsIItON9yVcNgasVY5EVJ_z9UCEYE7ifS6es_em8GXuQSZjL4elMAOcYKY-mFqvK7XoIYiCdoO9fXcs76s27BFjIlZ-jibt94sXMKAMiW-HDhL8Fx6YgFDMjXCKJuqgQvL6f2QokApfLDSvnpgf5uRCpVCyjlevWvENzKb2pD1gJvWBrOj_kU8HsHYg8siO1GP2yGFdEgOS79jFlelYdFjbEs_cIizY-X6" }
- ]
- }
- ]);
-
- const [groceries, setGroceries] = useState([
- { id: "g_milk", name: "Amul Taaza Milk (1L)", brand: "Amul", price: 56, weight: "1L", image: "https://images.unsplash.com/photo-1563636619-e9143da7973b?w=200&auto=format&fit=crop&q=60", stock: 0, latent_demand: 48, restock: 55, replacementName: "GoodLife Tetra Pack Milk (1L)" },
- { id: "g_tomatoes", name: "Fresh Tomatoes (500g)", brand: "Organic Farms", price: 32, weight: "500g", image: "https://images.unsplash.com/photo-1595855759920-86582396756a?w=200&auto=format&fit=crop&q=60", stock: 3, latent_demand: 24, restock: 30 },
- { id: "g_bananas", name: "Organic Bananas (1 doz)", brand: "Fresh Produce", price: 60, weight: "1 Dozen", image: "https://images.unsplash.com/photo-1571771894821-ce9b6c11b08e?w=200&auto=format&fit=crop&q=60", stock: 18, latent_demand: 82, restock: 90 }
- ]);
-
- const [disputesQueue, setDisputesQueue] = useState([
- { id: "disp_1", customer: "Gaurav Nayak", merchantId: "rest_behrouz", type: "Cold Delivery", text: "Mutton Biryani was cold and dry on arrival.", items: "1x Dum Gosht Biryani", status: "PENDING", refundAmt: 349 },
- { id: "disp_2", customer: "Anjali Patnaik", merchantId: "rest_yoko_ono", type: "Missing Items", text: "Did not receive the salmon nigiri pieces.", items: "1x Salmon Nigiri (2pcs)", status: "PENDING", refundAmt: 320 }
- ]);
-
- // Dineout Hotels Database
- const mockHotels = [
- { id: "hot_mayfair", name: "Mayfair Lagoon", cuisine: "Multi-Cuisine · Premium Buffet", rating: 4.8, distance: "3.0 km", costForTwo: 2500, image: "https://images.unsplash.com/photo-1566073771259-6a8506099945?w=300&auto=format&fit=crop&q=60", slots: ["07:30 PM", "08:00 PM", "09:00 PM", "09:30 PM"] },
- { id: "hot_swosti", name: "Swosti Grand Hotels", cuisine: "North Indian · Bar & Grill", rating: 4.5, distance: "1.8 km", costForTwo: 1800, image: "https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=300&auto=format&fit=crop&q=60", slots: ["07:00 PM", "08:30 PM", "09:00 PM"] },
- { id: "hot_taj", name: "Taj Vivanta", cuisine: "Global Gourmet · Fine Dine", rating: 4.9, distance: "4.5 km", costForTwo: 4000, image: "https://images.unsplash.com/photo-1542314831-068cd1dbfeeb?w=300&auto=format&fit=crop&q=60", slots: ["08:00 PM", "09:30 PM"] }
- ];
-
- // Forms states for Admin additions
- const [newRestName, setNewRestName] = useState("");
- const [newRestCuisine, setNewRestCuisine] = useState("");
- const [newRestImage, setNewRestImage] = useState("");
- const [newRestSLA, setNewRestSLA] = useState(25);
- const [newRestExclusive, setNewRestExclusive] = useState(false);
- const [newCouponCode, setNewCouponCode] = useState("");
- const [newCouponPct, setNewCouponPct] = useState(20);
- const [newCouponMin, setNewCouponMin] = useState(300);
-
- // Sync theme and festival attributes
- useEffect(() => {
- document.body.setAttribute('data-theme', theme);
- document.body.setAttribute('data-festival', festivalTheme);
- if (theme === 'dark') {
- document.documentElement.classList.add('dark');
- } else {
- document.documentElement.classList.remove('dark');
- }
- }, [theme, festivalTheme]);
-
- // Animated rider track simulation loop
- useEffect(() => {
- let interval;
- if (activeOrder) {
- interval = setInterval(() => {
- setRiderProgress(prev => {
- if (prev >= 100) {
- setActiveOrder(prevOrder => ({ ...prevOrder, status: "Delivered!" }));
- const totalSpend = activeOrder.items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
- const totalCals = activeOrder.items.reduce((sum, item) => sum + (item.calories || 0) * item.quantity, 0);
-
- // Increment streaks
- setStreakOrders(prevStreak => prevStreak + 1);
-
- setExpenseLogs(prevLogs => [
- ...prevLogs,
- { id: Date.now(), name: "Today", amount: totalSpend, calories: totalCals }
- ]);
- clearInterval(interval);
- return 100;
- }
- return prev + 1;
- });
- }, 500);
- }
- return () => clearInterval(interval);
- }, [activeOrder]);
-
- // ─── OAuth Redirect Callback Handler ───────────────────────────────────────
- useEffect(() => {
- const params = new URLSearchParams(window.location.search);
- const code = params.get('code');
- const state = params.get('state');
-
- if (code && state) {
- const savedState = localStorage.getItem('swiggy_oauth_state');
- if (state !== savedState) {
- console.warn("[OAuth] CSRF state mismatch!");
- }
-
- // Clean up state
- localStorage.removeItem('swiggy_oauth_state');
-
- // Exchange code for token
- API.exchangeCode(code, state).then(data => {
- if (data && data.access_token) {
- localStorage.setItem('swiggy_access_token', data.access_token);
- setIsLoggedIn(true);
- setAppView('hub');
- } else {
- alert("Swiggy connection failed: " + (data?.error_description || "Unknown error"));
- }
- window.history.replaceState({}, document.title, window.location.pathname);
- }).catch(err => {
- console.error("[OAuth] Exchange error:", err);
- window.history.replaceState({}, document.title, window.location.pathname);
- });
- }
- }, []);
-
- // ─── Backend Integration — on-mount data sync ─────────────────────────────
- useEffect(() => {
- // 1. Hydrate restaurants from backend
- API.fetchRestaurants().then(data => {
- if (data && Array.isArray(data) && data.length > 0) {
- // Merge backend list with local menus (backend doesn't store menus yet)
- setRestaurants(prev => {
- const merged = [...prev];
- data.forEach(beRest => {
- const existing = merged.find(r => r.id === beRest.id);
- if (!existing) merged.push({ ...beRest, menu: [] });
- else Object.assign(existing, { ...beRest, menu: existing.menu });
- });
- return merged;
- });
- }
- });
-
- // 2. Hydrate coupons from backend
- API.fetchCoupons().then(data => {
- if (data && Array.isArray(data) && data.length > 0) {
- setCoupons(data);
- }
- });
-
- // 3. Hydrate dineout reservations from backend
- API.fetchDineoutReservations().then(data => {
- if (data && Array.isArray(data) && data.length > 0) {
- setReservations(data);
- }
- });
-
- // 4. Hydrate expense logs from backend
- API.fetchExpenseLogs().then(data => {
- if (data && Array.isArray(data) && data.length > 0) {
- setExpenseLogs(data.map(e => ({ id: e.id, name: e.date || e.name || 'Day', amount: e.amount, calories: e.calories })));
- }
- });
-
- // 5. Hydrate festival theme from backend
- API.fetchFestivalSettings().then(data => {
- if (data?.festival_theme) setFestivalTheme(data.festival_theme);
- });
- }, []);
-
- // ─── Backend Integration — live WebSocket metrics ────────────────────────
- const [liveMetrics, setLiveMetrics] = useState(null);
- useEffect(() => {
- const ws = API.connectLiveMetrics(data => {
- setLiveMetrics(data);
- });
- return () => ws.close();
- }, []);
-
- // ─── Backend Integration — ML robustness polling (every 15s) ────────────
- const [mlRobustness, setMlRobustness] = useState(null);
- useEffect(() => {
- const poll = () => {
- API.fetchRobustness().then(data => {
- if (data) setMlRobustness(data);
- });
- };
- poll();
- const iv = setInterval(poll, 15000);
- return () => clearInterval(iv);
- }, []);
-
- // ─── Backend Integration — availability metrics ──────────────────────────
- const [availabilityMetrics, setAvailabilityMetrics] = useState(null);
- useEffect(() => {
- API.fetchAvailabilityMetrics('store_01').then(data => {
- if (data) setAvailabilityMetrics(data);
- });
- }, []);
-
- // ─── Backend Integration — bump rate metrics ─────────────────────────────
- const [bumpRateMetrics, setBumpRateMetrics] = useState(null);
- useEffect(() => {
- API.fetchBumpRate().then(data => {
- if (data) setBumpRateMetrics(data);
- });
- }, []);
-
- // ─── Backend Integration — store profitability ───────────────────────────
- const [profitabilityData, setProfitabilityData] = useState({});
- useEffect(() => {
- ['store_01', 'store_02', 'store_03'].forEach(storeId => {
- API.fetchProfitability(storeId).then(data => {
- if (data) setProfitabilityData(prev => ({ ...prev, [storeId]: data }));
- });
- });
- }, []);
-
-
-
- // Dynamic Loyalty Tier Calculations based on spent levels
- const getTotalSpent = () => expenseLogs.reduce((sum, log) => sum + log.amount, 0);
-
- const getLoyaltyTier = () => {
- const total = getTotalSpent();
- if (total >= 10000) return { name: "VIP Platinum Elite", color: "from-[#6C63FF] via-[#A078FF] to-[#00D4AA]", limit: 10000, cashback: 10, bg: "glow-primary" };
- if (total >= 5000) return { name: "Gold Executive", color: "from-[#FFB347] to-[#FF4757]", limit: 10000, next: "VIP Platinum Elite", cashback: 5, bg: "glow-gold" };
- return { name: "Silver Explorer", color: "from-[#A0A0B8] to-[#606075]", limit: 5000, next: "Gold Executive", cashback: 3, bg: "" };
- };
-
- const currentTier = getLoyaltyTier();
-
- // Helpers
- const getCartSubtotal = () => cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
-
- const getPackingFee = () => (cart.length > 0 ? 15 : 0);
-
- const getGSTAmount = () => Math.round(getCartSubtotal() * 0.05 * 100) / 100;
-
- const getDonations = () => {
- let amount = 0;
- if (donateClimate) amount += 2;
- if (donateFoodSafety) amount += 2;
- return amount;
- };
-
- const getDeliveryFee = () => {
- if (currentTier.name === "VIP Platinum Elite" || isPro) return 0;
- if (currentTier.name === "Gold Executive" && getCartSubtotal() >= 300) return 0;
-
- if (cart.length > 0 && cart[0].restaurantId === 'im_store') return 15;
- if (cart.length > 0) {
- const rest = restaurants.find(r => r.id === cart[0].restaurantId);
- if (rest && rest.isExclusive) return 0;
- }
- return stormSurge ? 45 : 30;
- };
-
- const getDiscountAmount = () => {
- const subtotal = getCartSubtotal();
- let discount = 0;
- if (appliedCoupon && subtotal >= appliedCoupon.minOrder) {
- if (appliedCoupon.code !== "FREEFEES") {
- discount = Math.round(subtotal * (appliedCoupon.pct / 100));
- }
- }
- if (isPro || currentTier.name === "VIP Platinum Elite") {
- discount += Math.round(subtotal * 0.1); // Extra 10% off
- } else if (currentTier.name === "Gold Executive") {
- discount += Math.round(subtotal * 0.05); // Extra 5% off
- }
- return discount;
- };
-
- const getCartTotal = () => {
- const subtotal = getCartSubtotal();
- const packing = getPackingFee();
- const gst = getGSTAmount();
- const delivery = (appliedCoupon?.code === "FREEFEES" || isPro || currentTier.name === "VIP Platinum Elite") ? 0 : getDeliveryFee();
- const donations = getDonations();
- const discount = getDiscountAmount();
- // Return precise 2-decimal rounded grand total
- return Math.round((subtotal + packing + gst + delivery + donations - discount) * 100) / 100;
- };
-
- const handleAddToCart = (item, restName, restId) => {
- setCart(prev => {
- const existing = prev.find(i => i.id === item.id);
- if (existing) {
- return prev.map(i => i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i);
- }
- return [...prev, { ...item, restaurantName: restName, restaurantId: restId, quantity: 1, protein: item.protein || 0, calories: item.calories || item.cal || 0 }];
- });
- };
-
- const handleAddOrCustomize = (item, restName, restId) => {
- if (item.id === 'dum_gosht') {
- setCustomizingItem({ dish: item, restaurantName: restName, restaurantId: restId });
- } else {
- handleAddToCart(item, restName, restId);
- }
- };
-
- const updateCartQty = (id, delta) => {
- setCart(prev => {
- return prev.map(item => {
- if (item.id === id) {
- const newQty = item.quantity + delta;
- return newQty <= 0 ? null : { ...item, quantity: newQty };
- }
- return item;
- }).filter(Boolean);
- });
- };
-
- const handlePlaceOrder = () => {
- if (cart.length === 0) return;
- const payload = {
- items: [...cart],
- restaurantName: cart[0].restaurantName,
- restaurantId: cart[0].restaurantId,
- total: getCartTotal()
- };
- setCheckoutPayload(payload);
- setPaymentScreenOpen(true);
- };
-
- const handleInstantReorder = () => {
- if (!lastOrderedItem) return;
- const payload = {
- items: [{ ...lastOrderedItem, quantity: 1 }],
- restaurantName: lastOrderedItem.restaurantName,
- restaurantId: lastOrderedItem.restaurantId,
- total: lastOrderedItem.price
- };
- setCheckoutPayload(payload);
- setPaymentScreenOpen(true);
- };
-
- const executePaymentSuccess = async (directPayload = null) => {
- const payload = directPayload || checkoutPayload;
- if (!payload) return;
-
- let orderId = `HF-${Math.floor(Math.random() * 8999) + 1000}`;
- let isRealOrder = false;
- const timestamp = new Date().toLocaleTimeString();
-
- // Fire Confetti Blast
- confetti({
- particleCount: 120,
- spread: 70,
- origin: { y: 0.6 }
- });
-
- const isSwiggyAuth = !!localStorage.getItem('swiggy_access_token');
-
- if (isSwiggyAuth) {
- try {
- setSecurityLogs(prev => [
- { time: timestamp, event: `SWIGGY REALTIME: Starting Swiggy Food MCP order placement flow...`, type: 'info' },
- ...prev
- ]);
-
- // 1. Fetch Swiggy address
- const addrRes = await API.fetchFoodAddresses();
- const addressId = addrRes?.structuredContent?.addresses?.[0]?.id;
-
- if (addressId) {
- // 2. Format items for cart update
- const swiggyItems = payload.items.map(item => ({
- id: item.id,
- quantity: item.quantity || 1
- }));
-
- // 3. Update Swiggy cart
- await API.updateFoodCart({ addressId, items: swiggyItems });
-
- // 4. Place Swiggy order
- const placeRes = await API.placeFoodOrder({ addressId, paymentMethod: "COD" });
-
- if (placeRes?.structuredContent?.orderId) {
- orderId = placeRes.structuredContent.orderId;
- isRealOrder = true;
- setSecurityLogs(prev => [
- { time: timestamp, event: `SWIGGY ORDER PLACED: Placed real checkout order ${orderId} via COD.`, type: 'success' },
- ...prev
- ]);
- }
- }
- } catch (err) {
- console.warn("[Swiggy Order placing failed, falling back to mock reservation]:", err);
- setSecurityLogs(prev => [
- { time: timestamp, event: `SWIGGY ORDER ERROR: Realtime order failed. Falling back to local lock manager: ${err.message}`, type: 'error' },
- ...prev
- ]);
- }
- }
-
- // Lock manager execution for local state validation & mock tracking
- if (!isRealOrder) {
- for (const item of payload.items) {
- let skuId = "g4"; // default mock restaurant item
- if (item.id === "g_milk") skuId = "g1";
- else if (item.id === "g_bananas") skuId = "g2";
- else if (item.id === "g_tomatoes") skuId = "g3";
-
- try {
- const res = await API.reserveInventory({
- order_id: orderId,
- store_id: "store_01",
- sku_id: skuId,
- qty_requested: item.quantity
- });
- if (res) {
- setSecurityLogs(prev => [
- { time: timestamp, event: `LOCK MANAGER: Reserved ${item.quantity}x ${item.name} (SKU: ${skuId}) via ${res.latency_ms ? `p99 Redis lock (${res.latency_ms}ms)` : 'lock manager'}.`, type: 'success' },
- ...prev
- ]);
- }
- } catch (err) {
- setSecurityLogs(prev => [
- { time: timestamp, event: `LOCK CONFLICT: Failed to reserve ${item.name}. Lock acquisition timeout or insufficient stock.`, type: 'error' },
- ...prev
- ]);
- }
- }
- }
-
- setActiveOrder({
- id: orderId,
- items: payload.items,
- status: isRealOrder ? "Order Confirmed by Swiggy" : "Preparing at kitchen",
- restaurantName: payload.restaurantName || "District Merchant",
- isRealOrder
- });
-
- if (payload.items.length > 0) {
- setLastOrderedItem({
- id: payload.items[0].id,
- name: payload.items[0].name,
- price: payload.items[0].price,
- restaurantName: payload.restaurantName,
- restaurantId: payload.restaurantId,
- protein: payload.items[0].protein,
- calories: payload.items[0].calories
- });
- }
-
- setCart([]);
- setAppliedCoupon(null);
- setCheckoutPayload(null);
- setActiveTab('orders');
- };
-
- const handleApplyCoupon = () => {
- const code = couponCodeInput.trim().toUpperCase();
- const matched = coupons.find(c => c.code === code);
- if (!matched) {
- setCouponMessage("Invalid Coupon Code ❌");
- return;
- }
- const subtotal = getCartSubtotal();
- if (subtotal < matched.minOrder) {
- setCouponMessage(`Min order value must be ₹${matched.minOrder} ⚠️`);
- return;
- }
- setAppliedCoupon(matched);
- setCouponMessage(`Coupon ${matched.code} applied successfully! ✓`);
- };
-
- const triggerCancelOrder = () => {
- if (!activeOrder) return;
- const itemsLabel = activeOrder.items.map(i => `${i.quantity}x ${i.name}`).join(', ');
- const originalPrice = activeOrder.items.reduce((sum, i) => sum + (i.price * i.quantity), 0);
- const timeNow = new Date().toLocaleTimeString();
-
- setRescueOffers([
- {
- order_id: `rescue_${activeOrder.id}`,
- restaurant_name: activeOrder.restaurantName || "Quick Kitchen",
- items: itemsLabel,
- original_price_inr: originalPrice,
- rescue_price_inr: Math.round(originalPrice * 0.5),
- sensory_quality_index: 94
- }
- ]);
-
- setSecurityLogs(prev => [
- { time: timeNow, event: `CANCEL: Order ${activeOrder.id} aborted by user.`, type: 'info' },
- { time: timeNow, event: `RESCUE QUEUE: Initialized cooling thermal curve (SQI=94/100).`, type: 'info' },
- ...prev
- ]);
-
- setActiveOrder(null);
- };
-
- const claimRescueOffer = (offer) => {
- const timestamp = new Date().toLocaleTimeString();
- setArbitrageMessage("Arbitrage Blocked: CO_LOCATION_PROXIMITY_ALERT, SHARED_IP_SUBNET_ALERT");
- setSecurityLogs(prev => [
- { time: timestamp, event: `ALERT: Blocked self-buyback exploit (Co-Location distance: 11 meters)`, type: 'error' },
- ...prev
- ]);
- setRescueOffers([]);
- };
-
- const handleCreateRestaurant = async (e) => {
- e.preventDefault();
- if (!newRestName.trim()) return;
- const payload = {
- name: newRestName,
- cuisine: newRestCuisine || "Global Cuisine",
- rating: 4.5,
- distance: "1.5 km",
- time: `${newRestSLA} min`,
- slaConfidence: 96,
- isAIPick: false,
- isExclusive: newRestExclusive,
- image: newRestImage.trim() || "https://images.unsplash.com/photo-1504674900247-0877df9cc836?w=300&auto=format&fit=crop&q=60"
- };
- // Optimistic update
- const localObj = { ...payload, id: `rest_${Date.now()}`, menu: [{ id: `dish_${Date.now()}_1`, name: "Signature Combo Pack", price: 299, rating: 4.5, desc: "A custom signature combo.", protein: 22, cal: 380, veg: true }] };
- setRestaurants(prev => [...prev, localObj]);
- // Persist to backend
- const result = await API.createRestaurant(payload);
- if (result?.restaurant) {
- // Replace local placeholder with backend ID
- setRestaurants(prev => prev.map(r => r.id === localObj.id ? { ...localObj, ...result.restaurant } : r));
- }
- setSecurityLogs(prev => [
- { time: new Date().toLocaleTimeString(), event: `ADMIN: Added merchant "${newRestName}" | Exclusive: ${newRestExclusive ? 'Yes' : 'No'} | Backend: ${result ? '✓ Synced' : '⚠ Local only'}`, type: 'success' },
- ...prev
- ]);
- setNewRestName("");
- setNewRestCuisine("");
- setNewRestImage("");
- setNewRestExclusive(false);
- };
-
- const handleCreateCoupon = async (e) => {
- e.preventDefault();
- if (!newCouponCode.trim()) return;
- const code = newCouponCode.toUpperCase().replace(/\s+/g, "");
- const newCop = {
- code,
- pct: parseInt(newCouponPct) || 10,
- minOrder: parseInt(newCouponMin) || 100,
- desc: `${newCouponPct}% off above ₹${newCouponMin}`
- };
- // Optimistic update
- setCoupons(prev => [...prev, newCop]);
- // Persist to backend
- const result = await API.createCoupon(newCop);
- setSecurityLogs(prev => [
- { time: new Date().toLocaleTimeString(), event: `ADMIN: Created coupon "${code}" (${newCouponPct}% off) | Backend: ${result ? '✓ Synced' : '⚠ Local only'}`, type: 'success' },
- ...prev
- ]);
- setNewCouponCode("");
- };
-
- const handleBookTableSlot = async (hotelName, slotTime) => {
- const localRes = {
- id: `res_${Math.floor(Math.random() * 89999) + 10000}`,
- hotel: hotelName,
- time: slotTime,
- party: 2,
- status: "CONFIRMED"
- };
- // Optimistic update
- setReservations(prev => [localRes, ...prev]);
- // Persist to backend
- const result = await API.reserveDineout({ hotel: hotelName, time: slotTime, party: 2 });
- if (result?.reservation) {
- setReservations(prev => prev.map(r => r.id === localRes.id ? { ...localRes, ...result.reservation } : r));
- }
- confetti({ particleCount: 60, spread: 50 });
- alert(`Table Reserved successfully at ${hotelName} for ${slotTime}! ✓`);
- };
-
- const handleSwapOOSItem = (itemId, altItemName, altPrice) => {
- setGroceries(prev => prev.map(item => {
- if (item.id === itemId) {
- return {
- ...item,
- name: altItemName,
- price: altPrice,
- stock: 12,
- brand: "GoodLife",
- image: "https://images.unsplash.com/photo-1563636619-e9143da7973b?w=200&auto=format&fit=crop&q=60"
- };
- }
- return item;
- }));
- setSecurityLogs(prev => [
- { time: new Date().toLocaleTimeString(), event: `REPLACEMENT: Swapped out-of-stock ${itemId} with alternative "${altItemName}"`, type: 'success' },
- ...prev
- ]);
- };
-
- const handleToggleGroceryStock = (id) => {
- setGroceries(prev => prev.map(item => {
- if (item.id === id) {
- const newStock = item.stock === 0 ? 20 : 0;
- setSecurityLogs(prevLogs => [
- { time: new Date().toLocaleTimeString(), event: `ADMIN: SKU ${id} stock toggled to ${newStock === 0 ? 'STOCKOUT (Censored)' : 'IN_STOCK'}`, type: 'info' },
- ...prevLogs
- ]);
- return { ...item, stock: newStock };
- }
- return item;
- }));
- };
-
- const processRefundTriage = (disputeId) => {
- const timestamp = new Date().toLocaleTimeString();
- setDisputesQueue(prev => prev.map(disp => {
- if (disp.id === disputeId) {
- const isBehrouz = disp.merchantId === 'rest_behrouz';
- let decision = "APPROVED (Auto-Refund)";
- let reason = "Approved: High tenant tenure, 0 recent refund requests.";
- let fraudProb = 0.08;
-
- if (isBehrouz) {
- decision = "FLAGGED (Manual Triage)";
- reason = "Flagged: Multiple claims from same IP subnet on high-end merchant.";
- fraudProb = 0.89;
- }
-
- setSecurityLogs(prevLogs => [
- { time: timestamp, event: `FRAUD GUARD: Dispute ${disputeId} processed. Decision: ${decision}. Score: ${(fraudProb * 100).toFixed(0)}%`, type: fraudProb > 0.5 ? 'error' : 'success' },
- ...prevLogs
- ]);
-
- return { ...disp, status: decision, fraudProb, reason };
- }
- return disp;
- }));
- };
-
- const handlePayUpgradeTier = (upgradeAmount, targetTierName) => {
- setExpenseLogs(prev => [
- ...prev,
- { id: Date.now(), name: "Upgrade", amount: upgradeAmount, calories: 0 }
- ]);
-
- // Blast confetti celebration
- confetti({
- particleCount: 150,
- spread: 80,
- origin: { y: 0.5 }
- });
-
- setSecurityLogs(prev => [
- { time: new Date().toLocaleTimeString(), event: `LOYALTY TIER: User completed direct pay upgrade to ${targetTierName} card.`, type: 'success' },
- ...prev
- ]);
- };
-
- const sendAgentMessage = async () => {
- if (!chatInput.trim()) return;
- const userMsg = chatInput.trim();
- setChatInput("");
-
- const newMessages = [...chatMessages, { sender: 'user', text: userMsg, time: new Date().toLocaleTimeString() }];
- setChatMessages(newMessages);
- setIsAgentThinking(true);
- setAgentThinkingTools(['agent_brain_router']);
-
- try {
- const response = await fetch('/api/v1/chat', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- message: userMsg,
- history: chatMessages.map(m => ({
- role: m.sender === 'user' ? 'user' : 'model',
- text: m.text
- }))
- })
- });
-
- const data = await response.json();
- setIsAgentThinking(false);
- setChatMessages(prev => [...prev, {
- sender: 'agent',
- text: data.reply,
- time: new Date().toLocaleTimeString(),
- tools: data.tools || []
- }]);
- } catch (err) {
- console.error("AI Agent Chat error:", err);
- setIsAgentThinking(false);
- setChatMessages(prev => [...prev, {
- sender: 'agent',
- text: "Sorry, I had trouble communicating with my backend brain. Please verify that your backend server is running and the Gemini API key is configured.",
- time: new Date().toLocaleTimeString(),
- tools: []
- }]);
- }
- };
-
- if (showLockScreen) {
- return (
- {
- setShowLockScreen(false);
- setShowSplash(true);
- }}
- />
- );
- }
-
- if (showSplash) {
- return (
- setShowSplash(false)}
- className="fixed inset-0 bg-[#FF5200] z-[9999] flex flex-col items-center justify-center overflow-hidden cursor-pointer font-sans"
- >
- {/* Swiggy Logo (Main File) */}
-
- {/* Swiggy Map Pin Logo in white */}
-
- {/* Swiggy text wordmark in white */}
-
- SWIGGY
-
-
-
- );
- }
-
- if (!isLoggedIn) {
- return setIsLoggedIn(true)} />;
- }
-
- if (appView === 'demand_oracle') {
- return setAppView('consumer')} />;
- }
-
- if (appView === 'eta_truth') {
- return setAppView('consumer')} />;
- }
-
- if (appView === 'refund_oracle') {
- return setAppView('consumer')} />;
- }
-
- if (appView === 'dineout_sniper') {
- return setAppView('consumer')} />;
- }
-
- if (appView === 'dispatch_map') {
- return setAppView('consumer')} />;
- }
-
- if (appView === 'admin') {
- return setAppView('consumer')} onNavigateView={(view) => setAppView(view)} />;
- }
-
- if (appView === 'merchant_stock_admin') {
- return setAppView('admin')} />;
- }
-
- if (appView === 'fleet_logistics_admin') {
- return setAppView('admin')} />;
- }
-
- if (appView === 'financial_ops_admin') {
- return setAppView('admin')} />;
- }
-
- if (appView === 'growth_analytics_admin') {
- return setAppView('admin')} />;
- }
-
- if (appView === 'refund_status') {
- return setAppView('admin')} />;
- }
-
- if (appView === 'help_support') {
- return setAppView('admin')} onOpenChatbot={() => setAppView('chatbot_help')} />;
- }
-
- if (appView === 'chatbot_help') {
- return setAppView('help_support')} />;
- }
-
- if (appView === 'festival_theme_manager') {
- return (
- {
- setFestivalTheme(newTheme);
- }}
- onBack={() => setAppView('admin')}
- />
- );
- }
-
- if (appView === 'loyalty') {
- return (
- setAppView('consumer')}
- onNavigate={(tab) => {
- if (tab === 'home') {
- setAppView('consumer');
- setActiveTab('home');
- } else if (tab === 'dineout') {
- setAppView('consumer');
- setActiveTab('dineout');
- } else if (tab === 'quick') {
- setAppView('consumer');
- setActiveTab('quick');
- } else if (tab === 'agent_chat') {
- setAppView('consumer');
- setChatOpen(true);
- }
- }}
- cartCount={cart.reduce((acc, item) => acc + (item.quantity || 1), 0)}
- />
- );
- }
-
- if (chatOpen) {
- return (
- setChatOpen(false)}
- messages={chatMessages}
- onSendMessage={sendAgentMessage}
- />
- );
- }
-
- if (activeOrder) {
- return (
- setActiveOrder(null)}
- riderPos={getInterpolatedPosition(HUB_COORDINATES.Bhubaneswar.route, riderProgress)}
- routePoints={HUB_COORDINATES.Bhubaneswar.route}
- orderStatus={riderProgress >= 100 ? "Arrived" : riderProgress >= 70 ? "Rider is delivering" : "Rider is picking up food"}
- etaMinutes={Math.max(1, Math.round(15 * (1 - riderProgress / 100)))}
- onChatClick={() => setChatOpen(true)}
- />
- );
- }
-
- if (paymentScreenOpen) {
- return (
- setPaymentScreenOpen(false)}
- onUpdateQuantity={updateCartQty}
- onPlaceOrder={(payload) => {
- const directPayload = {
- items: cart,
- restaurantName: cart[0]?.restaurantName || 'Instamart Store',
- restaurantId: cart[0]?.restaurantId || 'im_store',
- total: payload.grandTotal
- };
- setCheckoutPayload(directPayload);
- setCart([]);
- setPaymentScreenOpen(false);
- setActiveOrder({
- id: 'ORD-' + (Math.floor(Math.random() * 89999) + 10000),
- items: cart,
- total: payload.grandTotal,
- status: 'Preparing your meal'
- });
- setRiderProgress(0);
- executePaymentSuccess(directPayload);
- }}
- coupons={coupons}
- />
- );
- }
-
- if (restaurantPageOpen && selectedRestaurant) {
- return (
- setRestaurantPageOpen(false)}
- onAddToCart={handleAddToCart}
- onCheckout={() => { setRestaurantPageOpen(false); setPaymentScreenOpen(true); }}
- cart={cart}
- />
- );
- }
-
- if (appView === 'consumer') {
- return (
- setChatOpen(true)}
- onOpenCheckout={() => setPaymentScreenOpen(true)}
- onOpenOps={() => setAppView('intel')}
- onOpenProfile={() => setAppView('loyalty')}
- cart={cart}
- />
- );
- }
-
return (
-
-
- {/* ─── Premium Glassmorphic Header ─── */}
- {!isMobileDevice && (
-
- )}
-
-
- {/* ─── Main Viewport Grid ─── */}
-
-
- {/* VIEW 1: CONSUMER EXPERIENCE */}
- {appView === 'consumer' && (
- setChatOpen(true)}
- onOpenCheckout={() => setPaymentScreenOpen(true)}
- onOpenOps={() => setAppView('admin')}
- cart={cart}
- />
- )}
-
- {/* VIEW 2: OPERATIONS COMMAND DESK (INTEL VIEW) */}
- {appView === 'intel' && (
-
-
-
-
Operations & Intel Command Center
-
- Active monitoring of Tobit MLE parameters, spatial route optimization algorithms, and anti-fraud filters.
-
-
-
-
-
- {/* Box 1: Tobit MLE — live from /api/v1/metrics/availability */}
-
-
-
- Q1: Tobit MLE Demand Estimator
- {availabilityMetrics && ● LIVE }
-
-
-
- Censored Rate:
- {availabilityMetrics ? `${(availabilityMetrics.censoring_rate * 100).toFixed(0)}%` : `${(censoringRate * 100).toFixed(0)}%`}
-
-
- Availability Rate:
- {availabilityMetrics ? `${(availabilityMetrics.availability_rate * 100).toFixed(1)}%` : '94.7%'}
-
-
- WMAPE Lift:
- {availabilityMetrics ? `+${(availabilityMetrics.wmape_lift * 100).toFixed(1)}%` : `+${forecastOutput.lift_pct.toFixed(1)}%`}
-
-
- Avg Wastage:
- {availabilityMetrics ? `${availabilityMetrics.average_wastage_units} units` : '4.2 units'}
-
-
-
-
- {/* Box 2: ETA Jitter Smoother — live from /api/v1/metrics/bump-rate */}
-
-
-
- Q2: ETA Jitter Smoother
- {bumpRateMetrics && ● LIVE }
-
-
-
- Raw MIMO Bumps:
- {bumpRateMetrics?.raw_mimo_bumps ?? 113}
-
-
- Gated Bumps:
- {bumpRateMetrics?.gated_smoother_bumps ?? 21}
-
-
- Suppression:
- {bumpRateMetrics ? `${bumpRateMetrics.jitter_suppression_pct}%` : '81.4%'}
-
-
- Storm Surge:
-
- {bumpRateMetrics?.zone_status ?? (stormSurge ? 'ACTIVE' : 'INACTIVE')}
-
-
-
-
-
- {/* Box 3: ML Robustness — live from /api/v1/metrics/robustness */}
-
-
-
- Q3: ML Robustness (PSI)
- {mlRobustness && ● LIVE }
-
-
- {mlRobustness ? (
- <>
- {Object.entries(mlRobustness.features_drift || {}).map(([feat, m]) => (
-
- {feat.replace('weather_', '').replace('_elapsed_sec', '_time')}:
-
- PSI {m.psi?.toFixed(3)}
-
-
- ))}
-
- Clipped Today:
- {mlRobustness.clipping_guard?.total_clipped_observations_today ?? 0}
-
-
API.triggerRetrain().then(r => r && setSecurityLogs(p => [{ time: new Date().toLocaleTimeString(), event: 'MLOPS: Manual retrain triggered via dashboard.', type: 'success' }, ...p]))}
- className="w-full mt-1 bg-[#6C63FF]/20 hover:bg-[#6C63FF]/40 border border-[#6C63FF]/30 text-[#6C63FF] py-1 rounded text-[9px] font-bold font-mono transition-all active:scale-95"
- >
- ⚡ TRIGGER RETRAIN
-
- >
- ) : (
- <>
- {rescueOffers.length > 0 ? (
-
-
Resale Opportunity Identified:
-
claimRescueOffer(rescueOffers[0])}>Claim Resale
-
- ) : (
-
Sybil-Guard: No active resale offers in pool.
- )}
- >
- )}
-
-
-
-
-
- {/* GIS Routing Map and security log terminal */}
-
-
-
Spatial Routing (Bhubaneswar Hub)
-
-
-
-
-
-
-
Live Console Logs
-
- {arbitrageMessage &&
{arbitrageMessage}
}
- {securityLogs.map((log, idx) => (
-
- [{log.time}]
- {log.event}
-
- ))}
-
-
-
-
- )}
-
- {appView === 'admin' && (
-
-
-
-
Operations Parameter Configurator
-
- Inject anomalies, monitor pick deadlines, review merchant portals, and configure logistics surge incentives.
-
-
-
- {[
- { id: 'system', name: '⚙️ System' },
- { id: 'restaurant', name: '🍳 Partner Portal' },
- { id: 'picking', name: '📦 Dark Store Pick' },
- { id: 'logistics', name: '🚴 Fleet Dispatch' }
- ].map(tab => (
- setAdminSubTab(tab.id)}
- className={`px-3 py-1.5 rounded text-[11px] font-mono font-bold transition-all active:scale-95 ${
- adminSubTab === tab.id
- ? 'bg-[#00D4AA] text-black shadow'
- : 'text-gray-400 hover:text-white hover:bg-white/5'
- }`}
- >
- {tab.name}
-
- ))}
-
-
-
- {/* CONDITIONAL SUB-TABS RENDERING */}
- {adminSubTab === 'system' && (
- <>
- {/* Two-Column Top Grid */}
-
-
- {/* Merchant Restaurant Creator */}
-
-
-
- storefront
- Merchant Restaurant Creator
-
-
-
-
-
- {/* Coupon & Offer Builder */}
-
-
-
- local_offer
- Coupon & Offer Builder
-
-
-
-
-
-
- {/* Three-Column Bottom Configurator Row */}
-
-
- {/* Column 1: Instamart Stock Controls */}
-
-
-
- inventory_2
- Instamart Stock Sync
-
-
-
- {groceries.map(item => (
-
-
-
- local_drink
-
-
- {item.name}
- SKU: SKU-{item.id.toUpperCase()}
-
-
-
0
- ? 'bg-[#00E676]/10 text-[#00E676] border-[#00E676]/30 hover:bg-[#00E676]/25'
- : 'bg-red-500/10 text-red-500 border-red-500/30 hover:bg-red-500/25'
- }`}
- onClick={() => handleToggleGroceryStock(item.id)}
- >
-
- 0 ? 'bg-[#00E676]' : 'bg-red-500'}`} />
- {item.stock > 0 ? 'IN' : 'OUT'}
-
-
-
- ))}
-
-
-
- {/* Column 2: System Parameters & Overrides */}
-
-
-
- tune
- Global Overrides
-
-
-
-
-
Festival Surge Profiles
-
- {['nominal', 'diwali', 'holi'].map(tName => (
- {
- setFestivalTheme(tName);
- setSecurityLogs(prev => [
- { time: new Date().toLocaleTimeString(), event: `ADMIN: Global festival override changed to "${tName.toUpperCase()}"`, type: 'success' },
- ...prev
- ]);
- }}
- className={`flex-1 py-1.5 rounded text-[10px] font-bold uppercase transition-all active:scale-95 ${
- festivalTheme === tName
- ? 'bg-[#6C63FF] text-white font-bold shadow'
- : 'bg-transparent text-gray-400 hover:text-white'
- }`}
- >
- {tName}
-
- ))}
-
-
-
-
-
-
- thunderstorm
- Monsoon Surge Alert
-
-
- setStormSurge(!stormSurge)}
- className="sr-only peer"
- id="stormSurgeToggle"
- />
-
-
-
-
Activates dynamic pricing multiplier +1.5x across delivery fleet.
-
-
-
- {/* Column 3: Refund Disputes */}
-
-
-
- support_agent
- Dispute Triage
-
-
-
- {disputesQueue.map(disp => (
-
-
- {disp.id || 'ORD-9921-A'}
- 2m ago
-
-
"{disp.text}"
-
{
- if (disp.status === 'PENDING') {
- processRefundTriage(disp.id);
- }
- }}
- >
- psychology
- {disp.status === 'APPROVED' ? 'Triage Approved' : 'Run AI Triage'}
-
-
- ))}
-
-
-
- >
- )}
-
- {/* TAB 2: PARTNER PORTAL */}
- {adminSubTab === 'restaurant' && (
-
- {/* Left Column: Live SLA Accepting queue */}
-
-
-
- Incoming Zomato/Swiggy Orders (SOP-01 SLA accepting)
-
-
- {restaurantOrders.map(order => (
-
- {order.status === 'PENDING' && (
-
-
- {order.limit - order.elapsed}s LEFT
-
- )}
-
- {order.id}
-
{order.name}
- {order.items}
- Value: ₹{order.price}
-
-
- {/* Progress Bar showing elapsed SLA accept limit */}
- {order.status === 'PENDING' && (
-
- )}
-
-
- {order.status === 'PENDING' ? (
- <>
-
{
- setRestaurantOrders(prev => prev.map(o => o.id === order.id ? { ...o, status: 'COOKING', elapsed: 0 } : o));
- setSecurityLogs(p => [{ time: new Date().toLocaleTimeString(), event: `SLA ACCEPT: Accepted order ${order.id} for preparation.`, type: 'success' }, ...p]);
- }}
- className="flex-grow bg-[#00D4AA] hover:bg-[#00D4AA]/80 text-black font-bold text-xs py-1.5 rounded transition-all active:scale-95"
- >
- Accept Order
-
-
{
- setRestaurantOrders(prev => prev.map(o => o.id === order.id ? { ...o, status: 'REJECTED' } : o));
- setSecurityLogs(p => [{ time: new Date().toLocaleTimeString(), event: `SLA REJECT: Merchant rejected order ${order.id}.`, type: 'error' }, ...p]);
- }}
- className="bg-white/10 hover:bg-white/20 text-white font-bold text-xs px-3 py-1.5 rounded transition-all active:scale-95"
- >
- Reject
-
- >
- ) : (
-
- Status:
- {order.status}
-
- )}
-
-
- ))}
-
-
-
- {/* Right Column: Kitchen state flow tracker */}
-
-
Merchant Kitchen SLA SOPs
-
-
-
Active Preparation Pipelines
-
- {restaurantOrders.filter(o => o.status === 'COOKING').length === 0 ? (
-
No items currently cooking.
- ) : (
- restaurantOrders.filter(o => o.status === 'COOKING').map(o => (
-
-
{o.id} - Preparing
-
- {
- setRestaurantOrders(prev => prev.map(order => order.id === o.id ? { ...order, status: 'READY FOR PICKUP' } : order));
- setSecurityLogs(p => [{ time: new Date().toLocaleTimeString(), event: `KITCHEN SOP: Marked order ${o.id} ready for delivery driver pickup.`, type: 'info' }, ...p]);
- }}
- className="bg-amber-500 text-black px-2 py-0.5 rounded text-[8px] font-bold"
- >
- Ready to Pack
-
-
-
- ))
- )}
-
-
-
-
-
Completed Ready-to-Deliver Queue
-
- {restaurantOrders.filter(o => o.status === 'READY FOR PICKUP').map(o => (
-
- {o.id}
- RIDER ASSIGNED
-
- ))}
-
-
-
-
-
- )}
-
- {/* TAB 3: DARK STORE PICKING */}
- {adminSubTab === 'picking' && (
-
- {/* Left Column: picking sequence checklist */}
-
-
-
- Blinkit Picking Layout & Sequence (SOP-02 Target: 90s)
-
-
- Pick Time:
- 90 ? 'bg-red-500/10 text-red-500' : 'bg-green-500/10 text-green-500'}`}>
- {Math.floor(pickingSLA / 60)}m {pickingSLA % 60}s
-
-
-
-
-
- {pickingList.map(item => (
-
-
-
- {item.location.split(',')[1].trim()}
-
-
-
{item.name}
- Location: {item.location} | Qty: {item.qty}
-
-
-
- {item.status === 'PENDING' ? (
- {
- setPickingList(prev => prev.map(i => i.id === item.id ? { ...i, status: 'PICKED' } : i));
- setSecurityLogs(p => [{ time: new Date().toLocaleTimeString(), event: `PICKING SOP: Scanned and verified barcode for item SKU ${item.id} in ${item.location}.`, type: 'success' }, ...p]);
-
- // Check if all items are picked to stop SLA timer
- const temp = pickingList.map(i => i.id === item.id ? { ...i, status: 'PICKED' } : i);
- if (temp.every(i => i.status === 'PICKED')) {
- setPickingActive(false);
- confetti({ particleCount: 50, spread: 45 });
- }
- }}
- className="bg-[#00E676] hover:bg-[#00E676]/80 text-black text-[10px] font-bold px-3 py-1 rounded transition-all active:scale-95 font-mono"
- >
- Scan Barcode
-
- ) : (
-
- ✓ VERIFIED
-
- )}
-
-
- ))}
-
-
- {/* Visual Pathway path grid optimizer */}
-
-
Optimized Picking Path Sequence:
-
- Aisle 1 (B2)
- ➔
- Aisle 2 (A1)
- ➔
- Aisle 5 (C3)
- ➔
- Billing Counter
-
-
-
-
- {/* Right Column: Picking operations manual override */}
-
-
Picking Console SOPs
-
-
-
Reset Picking Queue
-
Simulate a fresh order arrival inside the Dark Store warehouse.
-
{
- setPickingList(prev => prev.map(i => ({ ...i, status: 'PENDING' })));
- setPickingSLA(0);
- setPickingActive(true);
- setSecurityLogs(p => [{ time: new Date().toLocaleTimeString(), event: `PICKING SOP: Reset picking queue. Target SLA timer restarted.`, type: 'info' }, ...p]);
- }}
- className="w-full bg-[#6C63FF] text-white py-1.5 rounded text-xs font-bold"
- >
- Reset & Generate Run
-
-
-
-
-
- )}
-
- {/* TAB 4: RIDER LOGISTICS */}
- {adminSubTab === 'logistics' && (
-
- {/* Left Column: Rider dispatch & route batching */}
-
-
- Active Delivery Fleet & Route Batching Resolver
-
-
-
- {riderList.map(rider => (
-
-
- {rider.name}
- {rider.status}
-
-
Location: {rider.location}
- {rider.batchedOrders.length > 0 && (
-
- Batched Runs:
- {rider.batchedOrders.map(oId => (
-
- {oId}
-
- ))}
-
- )}
-
- ))}
-
-
- {/* Batch routing simulator details */}
-
-
Logistics Engine SOP-03: Route Batching Rules
-
- Assigning two separate orders destined for co-located apartments to a single rider reduces cost per delivery (CPD) by 34% and improves rider payouts during peak surge windows.
-
-
-
-
- {/* Right Column: Fleet weather modifiers */}
-
-
Weather & Surge Modifiers
-
-
-
-
- Rain Storm Incentives
- Applies +₹20 / order to rider payouts
-
-
- {
- setStormSurge(!stormSurge);
- setSecurityLogs(p => [{ time: new Date().toLocaleTimeString(), event: `LOGISTICS SOP: Storm Surge ${!stormSurge ? 'ENABLED' : 'DISABLED'}. Rain incentive payouts recalculated.`, type: !stormSurge ? 'success' : 'error' }, ...p]);
- }}
- className="sr-only peer"
- />
-
-
-
-
-
- Delivery Fee (Consumer side):
- {stormSurge ? '₹45 (Rain Surge)' : '₹30'}
-
-
-
-
- )}
-
- )}
-
-
-
- {/* ─── SCREEN: Floating AI Agent Chat Drawer ─── */}
- {chatOpen && (
-
setChatOpen(false)}>
-
e.stopPropagation()}>
-
-
-
setChatOpen(false)}>
-
-
-
-
-
- {chatMessages.map((msg, idx) => (
-
- ))}
-
-
-
-
-
setChatInput(e.target.value)}
- onKeyDown={(e) => {
- if (e.key === 'Enter') sendAgentMessage();
- }}
- />
-
-
-
-
-
-
-
-
- )}
-
- {/* Tobit Forecast Modal */}
- {activeGroceryForecast && (
-
setActiveGroceryForecast(null)}>
-
e.stopPropagation()}>
-
Tobit Latent Demand Model
-
-
- Imputed Latent Demand:
- {activeGroceryForecast.latent_demand} units / day
-
-
-
setActiveGroceryForecast(null)}>Dismiss
-
-
- )}
-
-
+
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
);
}