As a frontend developer, implement the Navbar section for the Splash page. Build the full Navbar component using React with useState (locationOpen, mobileMenuOpen, selectedLocation, isScrolled) and useEffect/useRef for scroll detection. Integrate framer-motion useScroll and useTransform for scroll-driven opacity/blur transitions. Render NAV_PAGES links (/Home, /Search, /Map, /Results, /Notifications), a location dropdown with LOCATIONS array (current/campus/downtown/suburb), GPS and Pin SVG icons, a mobile hamburger menu with AnimatePresence open/close animation, and a UserIcon button. Import from '../styles/Navbar.css'. Note: this component may already exist from a prior page — check before recreating.
As a backend developer, implement the /api/places/search FastAPI endpoint that accepts query params: lat, lng, radius_km, category (mall/hospital/school/temple/park/medical), sort_by (distance/crowd/rating), crowd_max (0-100), and page/per_page for pagination. Integrate with OpenStreetMap Nominatim and Overpass API to fetch real nearby POIs. Returns paginated JSON with place id, name, category, address, lat, lng, distance_km, rating, crowd_percentage, crowd_level (low/medium/high), is_open, opening_hours. Required by: ResultsPlacesList, SearchResults, MapIntegration, MapViewport sections.
As a backend developer, implement CRUD FastAPI endpoints for notifications: GET /api/notifications (paginated, filterable by type: crowd/place/schedule/system, sort by newest/oldest/unread), POST /api/notifications/{id}/read (mark as read), POST /api/notifications/read-all, DELETE /api/notifications/{id}, GET /api/notifications/archived, POST /api/notifications/{id}/restore. Implement POST /api/notifications/settings to save user notification preferences (toggles, quiet hours, digest frequency) in MongoDB. Use MongoDB collection 'notifications' with fields: id, type, title, message, is_read, created_at, place_id (optional), lat/lng (optional). Required by: NotificationsAlertsList, NotificationsSettings, NotificationsArchived, NotificationsFilters, NotificationsHeader sections.
As a data engineer, define MongoDB collections and Pydantic models for the Scenic-Mall backend: (1) places collection — id, name, category, address, lat, lng, phone, website, hours, amenities, crowd_capacity; (2) crowd_snapshots — place_id, timestamp, percentage, level; (3) notifications — id, user_id, type, title, message, is_read, is_archived, created_at, place_id, lat, lng; (4) reviews — id, place_id, author, rating, text, verified, visit_type, helpful_count, created_at; (5) user_notification_settings — user_id, toggles, quiet_hours, digest. Create seed script (seed_db.py) populating 10+ demo places across New Delhi coords (lat~28.61, lng~77.20) with crowd and review data. Use Motor (async MongoDB driver) for FastAPI integration.
As a DevOps engineer, set up environment configuration for the project: create .env.example with required variables (MONGODB_URL, LITELLM_BASE_URL, LITELLM_API_KEY, OPENAI_MODEL, OSM_NOMINATIM_URL, OSM_OVERPASS_URL, FRONTEND_URL, JWT_SECRET_KEY, CORS_ORIGINS). Configure FastAPI CORSMiddleware to allow frontend origin. Set up pydantic-settings BaseSettings class (config.py) to load and validate env vars at startup. Add a /api/health endpoint returning service status, MongoDB connection state, and version. Ensure docker-compose.yml mounts .env and sets environment variables for both frontend and backend services.
As a frontend developer, implement a useGeolocation custom hook in src/hooks/useGeolocation.js that wraps navigator.geolocation.watchPosition to provide real-time {lat, lng, accuracy, error, loading} state. Implement a useLocationPermission hook returning {status: 'granted'|'denied'|'prompt', requestPermission()}. Create a LocationContext provider that stores the current user coordinates globally and exposes them app-wide. This is required by HomeLocationPermission section (permission flow), HomeVoiceSearch (GPS-based search), SearchInput (auto-populate location), MapViewport (map centering), and ResultsFilterBar (distance calculation). Fallback to default Delhi coordinates (28.6139, 77.2090) when GPS unavailable.
As a frontend developer, set up the global theme and design system for Scenic-Mall. Create src/styles/theme.js (or theme.css) exporting the full color palette: primary #1A73E8, primary_light #E8F0FE, secondary #FF6F61, accent #FFD700, highlight #FFA500, bg #FFFFFF, surface rgba(240,240,240,0.8), text #333333, text_muted #777777, border rgba(200,200,200,0.5). Configure global CSS custom properties (--color-primary, etc.) in src/styles/global.css. Set up shared utility CSS classes for crowd level badges (low/medium/high/very_high), category color swatches (mall/hospital/school/temple/park/medical), and reusable card/panel styles. Install and configure framer-motion, gsap (with ScrollTrigger), @react-three/fiber, @react-three/drei, and leaflet as project dependencies. Create src/styles/index.css entry point importing all base styles.
As a frontend developer, create src/config/env.js that centralizes all environment variable access: REACT_APP_API_URL (backend base URL), REACT_APP_WS_URL (WebSocket base URL), REACT_APP_OSM_TILE_URL (OpenStreetMap tile server, default https://tile.openstreetmap.org/{z}/{x}/{y}.png), REACT_APP_DEFAULT_LAT (28.6139), REACT_APP_DEFAULT_LNG (77.2090). Create .env.example listing all required frontend env vars. Update api.js (task d975fe36) to import from this config module. Update MapViewport (task 630ea784) and NotificationsAlertsList (task 2dc387cd) OsmMapTile to use REACT_APP_OSM_TILE_URL. Ensures environment parity between local dev and production deployments.
As a frontend developer, implement the SplashHero section. Build the hero with framer-motion containerVariants/wordVariants/subVariants/ctaVariants/statsVariants for staggered word-by-word headline animation of HEADLINE_WORDS array (Discover/Your/City/Smarter with accent styling). Use gsap for floating PINS array (6 pins: mall/hospital/park/school/temple/market) with per-pin amplitude and duration sinusoidal hover animations via useRef and useEffect. Render STATS bar (500+ Nearby Places, Live Crowd Density, Voice Assisted Search, 6 Place Categories) with PinSvgIcon per pin and ExploreArrow CTA button. Import from '../styles/SplashHero.css'. Uses useEffect, useRef, useAnimation from framer-motion.
As a frontend developer, implement the SplashValueProps section. Render three ValueCard components from the VALUE_PROPS array (Search Nearby Places, View Crowd Density, Voice Assisted) each with a tag, title, description, SVG icon (BuildingIcon/PeopleIcon/MicIcon), and CTA link (ArrowRightIcon). Each card uses useState(isHovered) and framer-motion whileInView with staggered delay (index * 0.12), whileHover scale: 1.05, and boxShadow animation. Animate entry from opacity: 0 / y: 32 using viewport once:true, margin: -60px. Import from '../styles/SplashValueProps.css'.
As a frontend developer, implement the SplashCityscape section — a 3D interactive cityscape using @react-three/fiber Canvas, OrbitControls, and Environment from @react-three/drei, plus THREE.js and gsap. Build a Building component (useRef meshRef, useState hovered) that uses useFrame to lerp scale on hover and interpolate emissive color between baseColor and goldColor (THREE.Color). Render BUILDINGS array (mall/hospital/school/temple/park) each with position, size, category, crowd percentage, and color. Show a selected building info panel with AnimatePresence slide-in, displaying label, category, emoji, desc, and a crowd gauge bar. Render LEGEND_ITEMS color key. Import from '../styles/SplashCityscape.css'. Uses useMemo for THREE.Color instances.
As a frontend developer, implement the SplashFeatureHighlight section. Use useRef (sectionRef, stepNumRef), useInView (once:true, margin: -80px), and useState(stepAnimated) to trigger a gsap counter animation on scroll-entry counting from 0 to 1 (duration 0.6, power2.out, delay 0.5). Animate the image column with imageVariants (x: '-100%' to 0, opacity slide-in) and overlayVariants (opacity fade) via framer-motion. Animate the text column with textColVariants (x: 80px to 0). Render placeMarkers array (4 markers: Mall/Hospital/Park/School with color-coded CSS classes sfh-place-marker-1 to -4) overlaid on a map mock. Render bullets array (3 feature bullets with colored dots). Include SearchIcon, CheckIcon, ArrowIcon SVG components. Import from '../styles/SplashFeatureHighlight.css'.
As a frontend developer, implement the SplashVoiceAssistance section. Build an animated voice UI with useState (listening state, active command index), useEffect for cycling through VOICE_COMMANDS array (6 commands: Find hospitals/Show less crowded malls/Parks open/Nearest school/temples within 5km/Low crowd clinics), and useRef for gsap waveform animation. Render a pulsing MicIcon button with AnimatePresence state transitions (idle/listening/result). Display EXAMPLE_CHIPS (4 chips: Find hospitals/Show less crowded areas/Parks open/Nearest mall) as interactive suggestion pills. Render feature cards using MapPinIcon, UsersIcon, TreeIcon, BuildingIcon, MicSmallIcon, SearchIcon SVGs. Import from '../styles/SplashVoiceAssistance.css'.
As a frontend developer, implement the SplashCrowdInsights section. Build a tabbed card switcher from CARDS array (Peak Hours 85%, Off-Peak 30%, Real-Time Alerts 62%) using useState for active card. Build a GaugeGraphic component (useRef gaugeRef/tweenRef, useState displayed) that animates an SVG circular gauge using gsap tween (val 0→target, duration 1.2, power2.out) when isActive, and reverses when inactive. Use CIRCUMFERENCE (2π×52) to compute strokeDashoffset on the SVG circle fill. Use framer-motion useMotionValue and useTransform for smooth transitions. Animate each card entry with framer-motion. Render statA and statB stat pairs per card. Import from '../styles/SplashCrowdInsights.css'.
As a frontend developer, implement the SplashUserPersonas section. Build PersonaCard components from the personas array (Alex Chen/Student, Maria Santos/Traveler, Priya Nair/Local Resident) with CSS 3D flip mechanic using useState(flipped). Flip triggers on mouseEnter/mouseLeave for desktop and onClick for mobile (detected via window.matchMedia max-width:767px). Front face shows avatar initial, role, emoji, and usecase text. Back face shows a benefits list (4 items per persona) with CheckIcon SVG checkmarks. Use useRef(cardRef) + useInView (once:true, margin: -60px) for scroll-entry animation. Each card has avatarClass and miniClass for persona-specific color theming (sup-avatar--student/traveler/resident). Render FlipIcon hint button. Import from '../styles/SplashUserPersonas.css'.
As a frontend developer, implement the SplashCallToAction section. Build a MagneticCTAButton component using useRef(btnRef), useState(magnetOffset, particles, isBursting), and useCallback. On mousemove compute dx/dy from button center and apply a magnetic pull effect via framer-motion animate prop (spring stiffness:300, damping:18, mass:0.5). On click: trigger generateParticles() (PARTICLE_COUNT=10 particles with angle-distributed x/y, random size 5–11, colors #FFD700/#1A73E8/#FF6F61), set isBursting, run gsap.fromTo scale 0.92→1 elastic.out, clear after 600ms. Use AnimatePresence to render burst particle divs. Render TRUST_ITEMS (Free to use / Real-time data / Voice-enabled) as trust badges. Use useInView + useAnimation for section scroll-entry. Import from '../styles/SplashCallToAction.css'.
As a frontend developer, implement the Footer section. Render three link columns: quickLinks (/Home/Search/Map/Notifications), exploreLinks (/Splash/Results/PlaceDetail), and legalLinks (Privacy Policy/Terms/Cookie Policy) using AnimatedLink and AnimatedLegalLink components — each with useState(hovered) and a framer-motion animated underline span (scaleX 0→1 on hover, duration 0.3). Render socialIcons array (LinkedIn/Twitter/GitHub) as AnimatedSocialIcon buttons with SVG path drawing animation using strokeDasharray/strokeDashoffset on hover. Use AnimatePresence for any hover overlays. Import from '../styles/Footer.css'. Note: this component may already exist from a prior page — check before recreating.
As a frontend developer, implement the Navbar section for the Home page. Reuse or extend the Navbar component from the Splash page if already built. Render NAV_PAGES array (Home, Search, Map, Results, Notifications) as navigation links. Build a location dropdown using useState(locationOpen/selectedLocation) with AnimatePresence toggling a LOCATIONS list (4 entries: current/campus/downtown/suburb) with PinIcon, GpsIcon, ChevronDown SVG components. Implement useScroll/useTransform for scroll-driven background opacity/blur. Handle mobile hamburger toggle via useState(mobileMenuOpen) with MenuIcon/CloseIcon swap. Use useEffect with scroll listener and useRef for dropdown close-on-outside-click.
As a backend developer, implement the /api/places/{place_id} FastAPI endpoint returning full place detail: name, category, address, lat/lng, phone, website, opening_hours (array per weekday), amenities list, crowd_density (current %), crowd_weekly_data (7-day heatmap array), peak_hours_data (hourly array), transport_options, reviews summary (avg_rating, count, breakdown by star), and photos. Integrates with OpenStreetMap Overpass API for base data. Required by: PlaceDetailHero, PlaceDetailCrowdDensity, PlaceDetailVenueInfo, PlaceDetailAmenities, PlaceDetailVisitTiming, PlaceDetailDirections, PlaceDetailReviews sections.
As a backend developer, implement the POST /api/voice/parse FastAPI endpoint that accepts {transcript: string, lat: float, lng: float} and returns structured search intent: {category, radius_km, crowd_preference (low/any), query_text}. Use LiteLLM routing to GPT to perform NLP intent extraction from voice transcripts like 'Find nearby malls with low crowd density' or 'Hospitals open now near me'. Returns parsed parameters that the frontend SearchInput and HomeVoiceSearch can pass directly to the /api/places/search endpoint. Include fallback regex-based parser for offline/error cases.
As a backend developer, implement an osm_service.py module wrapping OpenStreetMap APIs: (1) Overpass API queries for nearby POIs by category and bounding box (mall: shop=mall, hospital: amenity=hospital, school: amenity=school, temple: amenity=place_of_worship+religion=hindu, park: leisure=park, medical: amenity=pharmacy); (2) Nominatim reverse geocoding for address lookup from lat/lng; (3) OSRM or Valhalla routing for distance/duration estimates for transport options (walk/bus/metro/cab). Implement async httpx client with retry logic and caching (Redis or in-memory TTL cache) to avoid rate-limiting. Expose functions: search_nearby(lat, lng, radius_m, category) -> List[Place], reverse_geocode(lat, lng) -> str, get_route(origin, dest, mode) -> RouteInfo.
As a frontend developer, implement a centralized API client in src/services/api.js using axios or fetch. Define base URL from REACT_APP_API_URL env var. Implement typed service functions: searchPlaces({lat, lng, radius, category, sort, crowdMax, page, perPage}), getPlaceDetail(placeId), getCrowdDensity(placeId), getCrowdHistory(placeId), getReviews(placeId, {rating, page}), markReviewHelpful(placeId, reviewId), getNotifications({type, sort, page}), markNotificationRead(id), markAllRead(), deleteNotification(id), getArchivedNotifications(), restoreNotification(id), getNotificationSettings(), saveNotificationSettings(settings), parseVoiceSearch({transcript, lat, lng}). All functions should handle loading/error states and be consumed by the respective section components.
As a frontend developer, set up React Router v6 in App.jsx with routes for all pages: / (Splash), /home (Home), /search (Search), /results (Results), /map (Map), /place/:placeId (PlaceDetail), /notifications (Notifications). Create a top-level App.jsx that wraps the router with all context providers in order: LocationContext, SearchContext, any auth/notification contexts. Configure lazy loading (React.lazy + Suspense) for each page component to optimize bundle size. Set up src/pages/ directory with index files for each page. Create a shared Layout component wrapping Navbar and Footer around page content where applicable. Configure environment variable REACT_APP_API_URL for the API base URL.
As a backend developer, set up the FastAPI application entry point (main.py) with: application factory pattern, lifespan context manager for MongoDB Motor connection pool init/teardown and APScheduler startup, router registration for all API modules (/api/places, /api/voice, /api/notifications), CORSMiddleware wired from config.py CORS_ORIGINS, global exception handlers (HTTPException, ValidationError, generic 500), and request logging middleware. Create the project package structure: app/routers/, app/models/, app/services/, app/schemas/, app/core/. Install dependencies: fastapi, uvicorn, motor, pydantic-settings, httpx, apscheduler, litellm. Create requirements.txt. Ensure the /api/health endpoint returns MongoDB ping status and app version.
As a frontend developer, implement the HomeHero section for the Home page. Render HEADLINE_WORDS array (Explore, Nearby, Places, Know, the, Crowd) as individual motion.span elements using wordVariants (hidden: opacity:0, y:40, rotateX:-30 → visible with delay 0.15+i*0.1 stagger). Apply subVariants for subtitle (delay:0.9) and ctaVariants for CTA buttons. Implement useMotionValue/useTransform for mouse parallax tilt on the hero card. Render MallIcon, HospitalIcon, SchoolIcon, ParkIcon floating badges with staggered useInView entrance via useRef. Include SearchIcon and MapIcon in CTA buttons. Use gsap for any supplementary entrance timeline effects. Manage useState for active place category pill.
As a frontend developer, implement the HomeCityscape section for the Home page. Build a React Three Fiber Canvas with 6 CATEGORIES (malls/#1A73E8, hospitals/#FF6F61, schools/#4CAF50, temples/#FF9800, parks/#2E7D32, medical/#E91E63). Render Building components as RoundedBox meshes (@react-three/drei) at category-specific positions and scales with useFrame lerping emissiveIntensity (target 0.6 on hover, 0 otherwise) via useRef(targetEmissiveIntensity/currentEmissiveIntensity). Use OrbitControls and Text (@react-three/drei) for category labels. On category click, use gsap to animate camera position toward CATEGORIES[id].position. Show a 2D overlay panel with selected category's places count, crowd level (crowdColor-coded), and icon. Use useState for hoveredCategory and selectedCategory. Implement useCallback for pointer event handlers.
As a frontend developer, implement the HomeVoiceSearch section for the Home page. Build a voiceState machine with useState cycling through 'idle' → 'listening' → 'complete'. On mic click, call navigator.mediaDevices.getUserMedia({audio:true}) via startRealAudio — create AudioContext/AnalyserNode (fftSize:64), connect MediaStreamSource, and drive WAVE_BAR_COUNT (7) bar heights via requestAnimationFrame reading getByteFrequencyData. Implement cleanupAudio (cancelAnimationFrame, stream.getTracks().stop(), audioCtx.close()) via useCallback. Simulate transcript typewriter from SAMPLE_TRANSCRIPT ('Find nearby malls with low crowd density') using setInterval on charIndex state. Render 7 animated waveform bars with AnimatePresence. Provide text input fallback with useState(textInput). Use useRef for audioCtxRef, analyserRef, animFrameRef, streamRef, intervalRef.
As a frontend developer, implement the HomeQuickCategories section for the Home page. Render 6 CATEGORIES (malls/hospitals/schools/temples/parks/medical) as horizontally scrollable CategoryPill components. Each CategoryPill uses useMotionValue(scrollX) and useTransform to apply a parallax iconOffsetX (scrollX * -0.04 * (index+1)) smoothed by useSpring (stiffness:200, damping:30). Implement ripple effect on click using useState(ripple) storing {x, y, key} from getBoundingClientRect, animated out via AnimatePresence. Track useState(activeCategory) for selected pill highlight. Use useRef on scroll container and useEffect to listen to scroll events updating the shared scrollX motion value. Use useCallback for onClick handlers.
As a frontend developer, implement the HomeCrowdDensityInfo section for the Home page. Render 5 CROWD_LEVELS (very-low/#4CAF50, low/#1A73E8, moderate/#FFA500, high/#FF6F61, very-high/#E53935) as interactive cards with className variants (cdi-card--very-low through cdi-card--very-high). Each card shows a bar indicator (1–5 filled bars matching the bars field), LEVEL_ICONS SVG (smiley/group/group+/alert/danger faces), description text, and a colored tag badge. Use useAnimation (framer-motion) to trigger staggered bar fill animation on card enter via useInView with useRef. Use useState for hoveredLevel to expand card details. Apply colorLight as card background and tagBg/tagColor for the badge on hover.
As a frontend developer, implement the HomeUserPersonas section for the Home page. Render 3 persona cards (Student/Campus Explorer, Traveler/City Navigator, Local Resident/Smart Planner) using PersonaCard component. Each PersonaCard uses useInView (once:true, margin:'-60px') via useRef and animates from initial {opacity:0, x:persona.entryDirection, y:30} (entryDirections: -60, 0, 60) to {opacity:1, x:0, y:0} with delay index*0.2 and ease [0.22,1,0.36,1]. Apply whileHover y:-8. Animate hup-card-accent (scaleX 0→1) with delay index*0.2+0.3. Render StudentIcon, TravelerIcon, ResidentIcon SVG components and workflow string. Track useState(hovered) per card for accent styling. Render ArrowIcon in workflow step display.
As a frontend developer, implement the HomeFeatureHighlights section for the Home page. Render 5 FEATURES (Real-time Location Search/search, Voice-Powered Interaction/mic, Live Crowd Density/crowd, Smart Filtering/filter, Map Integration/map) as numbered feature rows. Resolve each feature's icon key via ICON_MAP dispatching to SearchIcon (circle + dashed inner circle), MicIcon (path+path+lines), CrowdIcon (path+circle+paths), FilterIcon (polygon), and MapIcon (polygon+lines) SVG components. Each feature row uses useInView (once:true) via useRef to trigger a framer-motion entrance animation (opacity:0,x:-30 → opacity:1,x:0) with delay index*0.12. Display num (01–05) as a large decorative label beside the title and description.
As a frontend developer, implement the HomeLocationPermission section for the Home page. Build a permission card using useState(enabled/animating) guarded by an if(enabled||animating) check. On handleEnable, construct a gsap.timeline() that: (1) scales btnRef.current to 0.95 then back to 1 with back.out(2), (2) animates glowRef.current boxShadow from '0 0 0px rgba(255,215,0,0)' to '0 0 60px rgba(255,215,0,0.6)' with opacity fade over 0.6s at offset '-=0.15'. Animate lock icon container background color to '#34a853' via framer-motion when enabled. Render 3 decorative parallax layers: hlp-decor-bg (3 orbs, translateY * -0.2), hlp-decor-mid (3 PinSvg pins, translateY * -0.4). Wrap card in whileInView (once:true, margin:'-60px') motion.div. Use checkRef for checkmark confirmation animation on completion.
As a frontend developer, implement the HomeCTA section for the Home page. Build two CTA buttons — primary (PARTICLE_COLORS_GOLD: #FFD700/#FFA500/#FFE066/#FFEC99/#E8C200) and secondary (PARTICLE_COLORS_CORAL: #FF6F61/#FF9A8B/#FF7B6F/#FFB4A2/#E85D50). On click, spawnParticles() uses useCallback to imperatively create PARTICLE_COUNT (16) div.hcta-particle elements in primaryParticleRef/secondaryParticleRef containers, sets random size (4–12px), color, boxShadow, then animates each with gsap.fromTo (x/y: 0→cos/sin*60-180px random spread, opacity:1→0, scale:1→0.2, duration:0.6–1.0, ease:'power2.out') removing particle in onComplete. Use useInView (once:true, margin:'-80px') via sectionRef for section entrance. Render 3 decorative parallax orbs (hcta-decor-orb--gold/blue/coral) at translateY * -0.2 and midground at -0.4.
As a frontend developer, implement the Footer section for the Home page. Reuse or extend the Footer component from the Splash page if already built. Render quickLinks (Home/Search/Map/Notifications), exploreLinks (Splash/Results/Place Detail), and legalLinks (Privacy/Terms/Cookie) using AnimatedLink and AnimatedLegalLink components — each tracks useState(hovered) to animate a motion.span underline (scaleX:0→1, duration:0.3/0.25, ease:'easeOut'). Render 3 SocialIcon components (LinkedIn/Twitter/GitHub) from socialIcons array using AnimatePresence hover states. Each SocialIcon SVG uses paths array with length metadata for potential stroke-dasharray animation. Apply motion.a with whileHover scale/color transitions on social buttons.
As a frontend developer, implement the Navbar section for the Search page. This component may already exist from the Home page — reuse if available. Build the sticky navbar with useScroll/useTransform (framer-motion) for scroll-based opacity transitions and isScrolled state via useEffect. Render NAV_PAGES array (Home, Search, Map, Results, Notifications) as anchor links. Implement location dropdown using useState(locationOpen) toggling LOCATIONS array (current/campus/downtown/suburb) with AnimatePresence for dropdown animation. Include PinIcon, ChevronDown, UserIcon, MenuIcon, CloseIcon, GpsIcon, BuildingIcon SVG components. Handle mobile hamburger menu with useState(mobileMenuOpen). Use useRef for dropdown click-outside detection.
As a backend developer, implement the /api/places/{place_id}/crowd FastAPI endpoint returning real-time crowd density percentage, crowd_level (low/medium/high/very_high), live_count estimate, capacity, and last_updated timestamp. Implement a background scheduler (APScheduler or FastAPI lifespan) to periodically compute synthetic crowd values based on time-of-day and day-of-week heuristics stored in MongoDB. Also implement /api/places/{place_id}/crowd/history returning 7-day hourly arrays for the heatmap. Required by: PlaceDetailCrowdDensity, PlaceDetailVisitTiming, ResultsPlacesList, MapViewport sections.
As a backend developer, implement FastAPI endpoints for place reviews: GET /api/places/{place_id}/reviews (paginated, filterable by star rating, returns author, date, rating, text, verified, visit_type, helpful_count) and POST /api/places/{place_id}/reviews/{review_id}/helpful (toggle helpful count for a review). Store reviews in MongoDB 'reviews' collection. Seed sample reviews for at least 3 demo places. Required by: PlaceDetailReviews section.
As a frontend developer, implement a SearchContext provider in src/context/SearchContext.jsx that stores and shares search state across pages: {query, category, lat, lng, radius, sortBy, crowdMax, results, totalCount, page, perPage, isLoading, error}. Expose actions: setSearchQuery, setCategory, setLocation, setFilters, setPage, triggerSearch (calls API client searchPlaces and updates results). This context enables Results page to receive search parameters set on the Search page, and allows Map page to display the same filtered results. Wire SearchContext into App.jsx provider tree alongside any existing contexts.
As an AI engineer, configure the LiteLLM routing layer for the Scenic-Mall backend. Create app/services/llm_service.py that initializes a LiteLLM router with GPT model config loaded from environment (LITELLM_BASE_URL, LITELLM_API_KEY, OPENAI_MODEL). Implement async wrapper functions: parse_voice_intent(transcript, lat, lng) -> dict that calls the LLM with a structured system prompt for extracting {category, radius_km, crowd_preference, query_text} from natural language voice inputs. Include fallback regex parser for when LLM is unavailable. Add retry logic (max 2 retries, exponential backoff). Wire into the /api/voice/parse endpoint (task 92d145cd). Ensure LiteLLM client is initialized once at app startup via lifespan and reused across requests.
As a backend developer, implement the crowd density background computation service in app/services/crowd_scheduler.py. Use APScheduler AsyncIOScheduler to run a job every 5 minutes that: (1) fetches all place IDs from MongoDB, (2) computes synthetic crowd percentage using time-of-day (peak hours 10am-2pm, 5pm-9pm) and day-of-week heuristics with seeded random noise per place_id, (3) determines crowd_level (low <33, medium <66, high <85, very_high >=85), (4) writes a new crowd_snapshots document and updates the place's current crowd_density field. Also expose a utility function get_current_crowd(place_id) used by the /api/places/{place_id}/crowd endpoint (task d8905743). Register the scheduler in FastAPI lifespan. Note: the /api/places/{place_id}/crowd endpoint task (d8905743-378c-4dca-8fd0-7af4d7d32aa8) depends on this service.
As a backend developer, implement an in-memory TTL cache for OpenStreetMap API responses to avoid rate-limiting by Nominatim and Overpass APIs. Create app/core/cache.py with a simple async TTL cache class (dict-based with timestamp tracking) supporting get(key), set(key, value, ttl_seconds), and invalidate(key). Configure TTLs: Overpass POI results 10 minutes, Nominatim geocode results 60 minutes, OSRM route results 5 minutes. Wire the cache into osm_service.py (task ea3e703a) so all external OSM calls check cache before making HTTP requests. Optionally support Redis as a drop-in replacement if REDIS_URL env var is set. This is a prerequisite for the OSM integration service (ea3e703a-6b4f-4407-b94c-04b36490c11c) to function efficiently under load.
As a frontend developer, implement a NotificationContext provider in src/context/NotificationContext.jsx that manages global notification state: {notifications, archivedNotifications, unreadCount, settings, isLoading, error}. Expose actions: fetchNotifications(filters), markRead(id), markAllRead(), deleteNotification(id), fetchArchived(), restoreNotification(id), fetchSettings(), saveSettings(settings). Wire API calls to the api.js service functions (getNotifications, markNotificationRead, etc. from task d975fe36). The context should auto-update unreadCount on any read/delete action. Wire NotificationContext into App.jsx provider tree. This context is required by NotificationsHeader (unreadCount, markAllRead), NotificationsAlertsList (notifications list), NotificationsSettings (settings fetch/save), NotificationsArchived (archived list + restore/delete), and NotificationsFilters (filter state).
As a frontend developer, implement mobile responsiveness across all pages and configure the app as a Progressive Web App (PWA) for mobile-first usage. Set up CSS media query breakpoints (mobile <768px, tablet 768-1024px, desktop >1024px) as CSS custom properties. Ensure all section layouts (Navbar hamburger menu, ResultsFilterBar mobile drawer, MapSidebar collapsible, PlaceDetailCrowdDensity responsive gauge) are functional on mobile viewports. Add viewport meta tag in index.html. Configure manifest.json with app name 'Scenic-Mall', icons, theme_color #1A73E8, background_color #FFFFFF, display standalone. Add a service worker (via Create React App's built-in workbox or manual) for offline fallback page. Test touch interactions for voice search mic button and 3D cityscape OrbitControls on mobile. Note: SRD requires the app to function seamlessly on various mobile devices.
As a frontend developer, implement a useVoiceRecognition custom hook in src/hooks/useVoiceRecognition.js that wraps the browser Web Speech API (SpeechRecognition / webkitSpeechRecognition). The hook should expose: {isListening, transcript, confidence, error, startListening(), stopListening(), resetTranscript()}. On transcript finalization, automatically call the backend /api/voice/parse endpoint (via api.js parseVoiceSearch) with the transcript and current GPS coordinates from LocationContext. Return structured intent to SearchContext so results are automatically fetched. Handle browser compatibility (check for SpeechRecognition support, fallback to text input if unsupported). This hook is consumed by HomeVoiceSearch (task 01be9d87), SearchInput (task 63577fbb), and VoiceFeedback (task 57a84efc).
As a backend developer, implement request rate limiting middleware for the FastAPI application to protect against abuse and OSM API quota overuse. Use slowapi (Starlette-compatible rate limiter) to apply per-IP limits: /api/places/search 30 req/min, /api/voice/parse 10 req/min, /api/places/{id}/crowd 60 req/min, all other endpoints 100 req/min. Configure rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) in responses. Return HTTP 429 with a JSON error body on limit exceeded. Register the limiter in main.py and add exception handler for RateLimitExceeded. This protects the OpenStreetMap Nominatim/Overpass APIs from being rate-limited due to excessive frontend requests.
As a frontend developer, implement a React ErrorBoundary class component in src/components/ErrorBoundary.jsx that catches runtime errors in the component tree and renders a fallback UI with the Scenic-Mall brand colors (#1A73E8 primary). Wrap each lazy-loaded page route in App.jsx with this ErrorBoundary. Also implement a global Axios/fetch interceptor in api.js that catches HTTP 429 (rate limit), 503 (service unavailable), and network errors, showing a toast notification via NotificationContext. Add a LoadingSpinner component (src/components/LoadingSpinner.jsx) used as the Suspense fallback for lazy-loaded pages. These cross-cutting concerns ensure graceful degradation per mobile UX requirements in the SRD.
As a frontend developer, implement the SearchHero section for the Search page. Build a Three.js particle system using useRef for canvasRef, rendererRef, sceneRef, cameraRef, particlesRef, frameRef, and clockRef. Create 320 particles using Float32Array for positions, sizes, and colors with a palette of blues and gold (#1A73E8, #4fa3f7, #E8F0FE, #FFD700, #FFA500, #ffffff). Set up PerspectiveCamera at z=28 with WebGLRenderer (alpha:true, antialias:true). Animate particles with velocity objects containing x/y/z/phase/speed properties in a useEffect animation loop. Display HINT_CHIPS array (Malls/Hospitals/Schools/Temples/Parks with emoji icons) and STATS array (2400+ Places, Live Crowd Data, 6 Categories). Use GSAP for content entrance animations via contentRef.
As a frontend developer, implement the SearchInput section for the Search page. Build a search bar using useState(query) and useState(isListening) with useRef for inputRef, submitBtnRef, and barRef. Render RECENT_SEARCHES array (Green Valley Mall, City General Hospital, Sunrise Park, St. Andrews School, Downtown Temple) as clickable chips using handleChipClick which sets query and triggers GSAP boxShadow animation on barRef. Implement handleClear to reset query. Implement handleVoice toggle with setTimeout simulating 3s voice capture ending with 'Nearby malls with low crowd'. Include SearchIcon, CloseIcon, MicIcon (with active fill prop), ArrowIcon, ClockIcon SVG components. Use useCallback for all handlers. Apply GSAP shake animation on empty submit via handleSubmit.
As a frontend developer, implement the VoiceFeedback section for the Search page. Build a voice feedback panel with useState for isListening, transcription, confidence, transcriptionIndex, charIndex, and isVisible. Use useRef for canvasRef, animFrameRef, barHeightsRef (Array of 32 BAR_COUNT values at 0.15), targetHeightsRef, panelRef, confidenceTweenRef, confidenceValRef, and typingTimerRef. Implement GSAP entrance animation on panelRef (opacity 0→1, y 18→0, scale 0.97→1, duration 0.55). Build typewriter effect with setTimeout cycling through SAMPLE_TRANSCRIPTIONS array (5 items) at 55+random(35)ms per char with 2200ms pause between. Render BAR_COUNT=32 animated audio bars on canvas. Display VOICE_SUGGESTIONS array (Malls near me, Open hospitals, Nearby parks, Low crowd places with emoji icons). Include MicIcon and CloseIcon SVG components.
As a frontend developer, implement the CategoryFilter section for the Search page. Build a horizontally scrollable tab bar using useState(activeId) initialized to 'all' and useState(sortIndex) for SORT_OPTIONS (Nearest First, Most Popular, Least Crowded). Render CATEGORIES array (All Places/48, Malls/12, Hospitals/8, Schools/9, Medical/7, Temples/5, Parks/7) each with inline SVG icons and count badges. Use useRef for scrollRef, tabRefs object, lineRef, and prevActiveRef. Implement GSAP-animated sliding indicator line (lineRef) that moves to active tab position on category change. Track scroll position with scroll event listener to toggle useState(showFadeLeft) and useState(showFadeRight) for gradient fade overlays. Use useCallback for tab click and sort handlers.
As a frontend developer, implement the CrowdDensityLegend section for the Search page. Build a static legend bar rendering DENSITY_ITEMS array with three entries: low (cdl-dot--low, 'Quiet — ideal time to visit'), medium (cdl-dot--medium, 'Moderate — expect some wait'), and high (cdl-dot--high, 'Busy — plan your visit accordingly'). Each item uses modifier classes (cdl-item--low/medium/high) and dot wrapper with aria-hidden spans. Include a cdl-divider separator and cdl-label-title heading. Apply appropriate ARIA roles (section aria-label='Crowd density legend', role='presentation' on items).
As a frontend developer, implement the SearchFooterCTA section for the Search page. Build a scroll-triggered CTA section using GSAP ScrollTrigger (registered via gsap.registerPlugin). Use useRef for rootRef, headingRef, subtextRef, statsRef, actionsRef, chipsRef, and eyebrowRef. Implement a GSAP timeline triggered at 'top 82%' with sequential fromTo animations for each ref (opacity 0→1, y staggered 12-22→0). Render CHIPS array (Live Crowd Data/#1A73E8, Voice Search/#FF6F61, GPS Tracking/#FFD700, Nearby Places/#FFA500) as colored pill badges. Display STATS array (500+ Places, 12 Categories, Live Crowd Data). Include MapPinIcon and CalendarIcon SVG components in primary/secondary CTA buttons. Apply gsap.context for cleanup via ctx.revert() on unmount.
As a frontend developer, implement the Footer section for the Search page. This component may already exist from Splash or Home pages — reuse if available. Build footer with framer-motion AnimatePresence and motion.a for animated links. Render quickLinks (Home, Search, Map, Notifications), exploreLinks (Splash, Results, PlaceDetail), and legalLinks (Privacy Policy, Terms, Cookie Policy) each using AnimatedLink and AnimatedLegalLink sub-components with useState(hovered) and motion.span underline scaleX 0→1 on hover. Render socialIcons array (LinkedIn, Twitter, GitHub) as SocialIcon components with useState(hovered) and SVG path animations. Display app branding and copyright text.
As a frontend developer, implement the Navbar section for the Results page. This component may already exist from previous Search page implementation (task 6af74b6f). If reusable, import and configure it for the Results page context. The Navbar uses framer-motion (useScroll, useTransform, AnimatePresence) for scroll-aware animations, manages locationOpen/mobileMenuOpen/selectedLocation state via useState, and renders a NAV_PAGES array linking to Home, Search, Map, Results, and Notifications. Includes a LOCATIONS dropdown with GPS/pin icons (PinIcon, GpsIcon, BuildingIcon, ChevronDown SVGs), a mobile hamburger menu (MenuIcon/CloseIcon), and a UserIcon avatar. Scroll detection via useEffect updates isScrolled state to toggle backdrop blur styling.
As a backend developer, implement the POST /api/voice/speak FastAPI endpoint that accepts {text: string, lang: string} and returns an audio stream or base64-encoded audio for text-to-speech voice feedback. Use a free TTS library (gTTS or pyttsx3) to synthesize responses like crowd density summaries ('Central City Mall is moderately crowded right now'). Wire into the LiteLLM service so voice responses can be generated after intent parsing. This endpoint supports the VoiceFeedback section (task 57a84efc) and HomeVoiceSearch (task 01be9d87) for full voice interaction loop. Depends on: FastAPI bootstrap (7b5ac743) and LiteLLM router (58b79b49).
As a backend developer, implement GET /api/geocode/reverse?lat={lat}&lng={lng} FastAPI endpoint that wraps the OpenStreetMap Nominatim reverse geocoding API. Returns {address, city, district, country, display_name}. Used by the frontend LocationContext and SearchInput to show the user's readable location string (e.g., 'Connaught Place, New Delhi'). Apply in-memory TTL cache (60 min) via app/core/cache.py (task a9227201). Depends on: OSM Integration Service (ea3e703a), Cache Layer (a9227201), FastAPI bootstrap (7b5ac743).
As a backend developer, implement GET /api/directions?from_lat={}&from_lng={}&to_lat={}&to_lng={}&mode={walk|bus|metro|cab} FastAPI endpoint. Use OSRM public API (router.project-osrm.org) or Valhalla for free routing. Returns {duration_min, distance_km, steps, polyline}. This powers the PlaceDetailDirections section (task 80e2abb7) transport option cards. Apply in-memory TTL cache (5 min) via cache.py. Depends on: OSM Integration Service (ea3e703a), Cache Layer (a9227201), FastAPI bootstrap (7b5ac743).
As a backend developer, implement GET /api/places/categories FastAPI endpoint returning each supported category (mall/hospital/school/temple/park/medical) with total count of nearby POIs and current average crowd_level for the user's area (lat/lng query params). Used by HomeCityscape (task 19316517) to display live category counts and crowd levels on the 3D building overlay panel, and by HomeQuickCategories (task a26ba18b) for count badges. Depends on: Places Search API (cf9911e5), Crowd Density API (d8905743), FastAPI bootstrap (7b5ac743).
As a backend developer, implement a WebSocket endpoint ws://api/ws/crowd/{place_id} in FastAPI that pushes crowd density updates to connected clients in real time. On connection, immediately send current crowd snapshot from MongoDB. Subscribe to APScheduler job completion events to broadcast new snapshots every 5 minutes to all clients subscribed to that place_id. Use FastAPI WebSocket and a simple connection manager (dict keyed by place_id). This enables PlaceDetailCrowdDensity (task 83ba0b0d) to show live updating crowd gauge without polling. Depends on: Crowd Density Background Scheduler (439e2c5b), FastAPI bootstrap (7b5ac743).
As a backend developer, implement app/services/notification_service.py that generates crowd alert notifications automatically. On each APScheduler crowd snapshot update cycle (every 5 min), check if any place transitions from medium→high or high→very_high crowd_level. If so, create a new notification document in MongoDB (type: 'crowd', title: '{place_name} is getting crowded', message, place_id, lat, lng, is_read: false). Expose a utility create_notification(user_id, type, title, message, place_id) used by other services. Wire into crowd_scheduler.py (task 439e2c5b). Required by: Notifications & Alerts API (eb363a4c). Note: depends on crowd scheduler (439e2c5b) and MongoDB models (070e7e33).
As a frontend developer, implement the SearchResults section for the Search page. Render PLACES array of 10 places (City Centre Mall, Green Valley Park, Apollo Hospital, Sunrise Engineering College, Shree Ram Temple, MedCare Pharmacy, Downtown Food Court, Lakeside Community School, The Grand Hypermarket, Riverside Central Park) each with emoji icon, iconBg color, distance, rating, reviews count, crowd percentage (0-88), crowdLevel (low/medium/high), crowdLabel, isOpen status, and href to /PlaceDetail. Use useState for active/hovered card tracking. Implement GSAP staggered card entrance animations via useRef and useEffect triggered by useInView or scroll. Show crowd progress bar filled to crowd% with color keyed by crowdLevel. Display star rating, review count, open/closed badge, and distance chip per card.
As a frontend developer, implement the MapIntegration section for the Search page. Build an interactive SVG map using useState for activePlace, zoom (default 1), gpsActive, centered, and popupPos ({x:50, y:50}). Render PLACES array of 8 locations (Horizon Mall, City Hospital, Green Valley Park, Sunrise Temple, Tech Campus, Central Pharmacy, Metro Plaza, Riverside School) as positioned markers at x/y percentage coordinates. Apply DENSITY_COLORS (#22c55e low, #FFD700 moderate, #FF6F61 high, #e11d48 very_high) to markers. Use useRef for mapRef, controlsRef, legendRef, and titleRef. Implement GSAP timeline entrance animations on titleRef. Show popup card on marker click positioned via popupPos state. Include zoom controls (+/-), GPS recenter button (GpsIcon SVG), and map toggle button (MapIcon SVG). Render LEGEND_ITEMS with density color dots.
As a frontend developer, implement the ResultsHeader section for the Results page. Uses gsap for entrance animations via useRef and useEffect on mount. Renders a breadcrumb trail with ChevronRightIcon SVG showing search context. Displays a CATEGORIES array (Malls, Hospitals, Schools, Parks, Temples, Pharmacies) with dynamic CategoryIcon components switching on type prop (mall/hospital/school/park/temple/pharmacy SVG variants). Includes SearchIcon, MapPinIcon, MapIcon, and TagIcon SVGs for contextual UI elements. Animates the header title and category chips in on load using GSAP timeline.
As a frontend developer, implement the ResultsFilterBar section for the Results page. Manages complex multi-state: activeCategory, crowdDensity (0-100 slider), distance (0-25km slider), sortBy (distance/crowd/rating), and a mobile drawerOpen with mirrored drawer state values. Uses gsap with animateIndicator callback to animate a sliding pill indicator (indicatorRef) under the active category button, computing left/width from getBoundingClientRect differences. CATEGORIES array (all/mall/hospital/school/temple/park/medical with emoji icons) rendered as horizontally scrollable tab bar with catBtnRefs for indicator positioning. SORT_OPTIONS dropdown with ChevronDownIcon. FilterIcon badge shows activeCount of non-default filters. XIcon clears individual filters. getSliderBackground utility generates CSS gradient for range inputs. Mobile drawer panel with AnimatePresence for slide-in animation.
As a frontend developer, implement the Footer section for the Results page. This component may already exist from previous Home/Search page implementations (tasks b68eecaa, 610c3c0f). If reusable, import and wire it for the Results page. Footer uses framer-motion (motion.a, AnimatePresence) for hover underline animations on links via scaleX transform. Renders three link groups: quickLinks (Home/Search/Map/Notifications), exploreLinks (Splash/Results/PlaceDetail), and legalLinks (Privacy/Terms/Cookie). AnimatedLink and AnimatedLegalLink sub-components manage local hovered state with onMouseEnter/onMouseLeave. socialIcons array (LinkedIn/Twitter/GitHub) with SVG path animations using stroke-dasharray/dashoffset reveal on hover. ftr-social-btn uses motion.a with hover lift transform.
As a frontend developer, implement the Navbar section for the Map page. This component is shared across pages — check if it already exists from Search or Results pages before recreating. Build using React with useState (locationOpen, mobileMenuOpen, selectedLocation, isScrolled) and useEffect/useRef for scroll detection. Integrate framer-motion useScroll and useTransform for scroll-driven opacity/blur transitions. Render NAV_PAGES links (/Home, /Search, /Map, /Results, /Notifications), a location dropdown with LOCATIONS array (current/campus/downtown/suburb) with GpsIcon and PinIcon SVGs, AnimatePresence mobile hamburger menu with MenuIcon/CloseIcon, ChevronDown dropdown indicator, and UserIcon button. Import from '../styles/Navbar.css'.
As a frontend developer, implement the Navbar section for the PlaceDetail page. Reuse or extend the Navbar component from previous pages (Home, Results, Map) if already built. Render NAV_PAGES array (Home, Search, Map, Results, Notifications) as navigation links. Build location dropdown using useState(locationOpen/selectedLocation) with AnimatePresence toggling LOCATIONS list (current/campus/downtown/suburb) with PinIcon, GpsIcon, ChevronDown, BuildingIcon SVG components. Implement useScroll/useTransform for scroll-driven background opacity/blur on isScrolled state. Handle mobile hamburger toggle via useState(mobileMenuOpen) with MenuIcon/CloseIcon swap. Use useEffect scroll listener and useRef for dropdown close-on-outside-click behavior.
As a frontend developer, implement the ResultsCount section for the Results page. Manages filters state (array of {id, label, icon} objects) and removing state (Set of IDs being animated out). INITIAL_FILTERS contains three chip tags: category-mall, radius-2km, crowd-low with BuildingIcon/PinIcon/PeopleIcon SVG mapping via iconMap. removeFilter() adds ID to removing Set then uses 240ms setTimeout to delete from filters array — enabling CSS exit animation. clearAll() marks all IDs for removal with 260ms delay. displayCount dynamically subtracts 3 per removed filter from INITIAL_COUNT (24), clamped to 0 via Math.max. XIcon and ClearAllIcon SVGs for chip removal and bulk clear. Renders rc-root layout with rc-summary count display and rc-sep divider.
As a frontend developer, implement the MapSidebar section. Build a collapsible sidebar using React with useState and useRef, animated via gsap. Render a CATEGORIES array of 6 filter chips (Malls #1A73E8, Hospitals #E53935, Schools #F57C00, Temples #7B1FA2, Parks #2E7D32, Medical #0288D1) each with inline SVG icons, toggleable active state, and color-coded highlight on selection. Render SORT_OPTIONS (Distance, Crowd) as a toggle button group with SVG icons. Include a place list panel below filters showing place cards with name, category badge, crowd density bar, and distance. Use gsap for sidebar slide-in entrance animation and staggered list item reveals. Import from '../styles/MapSidebar.css'.
As a frontend developer, implement the MapViewport section. Integrate Leaflet.js loaded dynamically via a CDN loader (loadLeaflet promise, leafletLoadPromise singleton) using useEffect and useRef (mapRef, mapInstanceRef). Initialize map centered on DEFAULT_CENTER [28.6139, 77.2090] at DEFAULT_ZOOM 14. Render PLACES array (8 places: malls/hospitals/parks in New Delhi lat/lng) as custom circular markers colored by CATEGORY_COLORS (mall #1A73E8, hospital #FF6F61, park #34A853) with crowd density ring using crowdColor() helper (green/yellow/orange/red thresholds at 0.33/0.55/0.75). On marker click show a popup with place name, crowdLabel() text, and category badge. Support heatmap overlay toggle with HeatmapIcon. Include ZoomInIcon, ZoomOutIcon, RecenterIcon SVG components wired to Leaflet zoom/setView calls. Import from '../styles/MapViewport.css'.
As a frontend developer, implement the MapControls section. Build a floating control panel using React with useState (zoomLevel default 14, layerMode 'street', isTracking false, trackingStatus string) and useRef (panelRef, layerRef, statusRef, trackBtnRef). On mount run a gsap.fromTo entrance animation on panelRef (gsap.context). Render ZoomInIcon/ZoomOutIcon buttons that increment/decrement zoomLevel clamped between ZOOM_MIN 1 and ZOOM_MAX 20 with gsap scale pop feedback on btnRef. Render LAYER_MODES toggle (Street with StreetViewIcon / Satellite with SatelliteIcon) that switches layerMode state. Render a TrackingOnIcon GPS tracking button that toggles isTracking and updates trackingStatus text, with gsap pulse animation on trackBtnRef when active. Animate layer switcher with gsap on layerRef change. Import from '../styles/MapControls.css'.
As a frontend developer, implement the MapLegend section. Build a collapsible legend panel using React with useState(isOpen default true) and useRef (bodyRef, itemsRef). On isOpen toggle run a gsap stagger animation querying '.ml-category-item, .ml-density-item, .ml-marker-item' from bodyRef (opacity 0→1, y -8→0, duration 0.28, stagger 0.04, ease power2.out, delay 0.05). Render CATEGORIES array (6 items: malls/hospitals/schools/temples/parks/medical) each with a colored swatch using swatchClass CSS (ml-swatch-malls through ml-swatch-medical) and CategoryIcon SVG dot. Render DENSITY_LEVELS (Sparse/Moderate/Crowded) with barClass color bars and desc text. Render MARKER_SIZES (Nearby/Mid-range/Distant) with dotClass sized dots and distance desc. Header uses MapPinIcon and ChevronDownIcon with aria-expanded toggle. Import from '../styles/MapLegend.css'.
As a frontend developer, implement the Footer section for the Map page. This component is shared across pages — check if it already exists from Search, Results, or Splash pages before recreating. Render three link columns: quickLinks (/Home/Search/Map/Notifications), exploreLinks (/Splash/Results/PlaceDetail), and legalLinks (Privacy Policy/Terms/Cookie Policy) using AnimatedLink and AnimatedLegalLink components — each with useState(hovered) and a framer-motion animated underline span (scaleX 0→1 on hover, duration 0.3/0.25). Render socialIcons array (LinkedIn/Twitter/GitHub) as social buttons with SVG path draw animation on hover using strokeDasharray/strokeDashoffset. Import from '../styles/Footer.css'.
As a frontend developer, implement the PlaceDetailHero section for the PlaceDetail page. Build a React Three Fiber Canvas rendering 12 BUILDINGS as boxGeometry meshes (width/depth 0.6) using useFrame to apply a slow sinusoidal y-rotation (Math.sin(elapsed*0.15+position[0])*0.04) via meshRef. Include CityscapeScene with ambientLight (0.5), two directionalLights (position [8,10,4] and [-6,5,-3]) and a pointLight (#FFD700, distance:14). Render a ground plane (planeGeometry 28×12, color '#0d1b35') rotated -PI/2. Display PLACE static data object (name: 'Central City Mall', rating:4.3, reviewCount:1284, distance, crowdStatus, openStatus, closingTime, floors, parking, wifi) with StarIcon components using getStarType() helper (pdh-filled/pdh-half/pdh-empty class variants). Use gsap for hero entrance timeline on mount via useRef.
As a frontend developer, implement the PlaceDetailCrowdDensity section for the PlaceDetail page. Build CrowdMeter component with an SVG circle gauge (r=82, CIRCUMFERENCE=2*PI*82) rendering a track arc (strokeDasharray CIRCUMFERENCE*0.78) and a fill arc with strokeDashoffset CIRCUMFERENCE*0.11 driven by CROWD_DENSITY (67). On mount, run two gsap.to() counter animations: displayDensity 0→67 (1.4s, power2.out) and displayCount 0→412 (1.6s, power2.out) via useState. Render PEAK_HOURS_DATA (8 time slots 8am–10pm) as a bar chart with pcd-bar-low/medium/high class variants via getBarClass(). Highlight CURRENT_HOUR_IDX=5. Implement day-selector tabs from DAYS array using useState(selectedDay) loading corresponding WEEKLY_DATA arrays for bar chart. Use getDensityClass/getDensityLabel helpers to display live crowd status label. Show CAPACITY=620 and LIVE_COUNT=412 stats.
As a frontend developer, implement the PlaceDetailVenueInfo section for the PlaceDetail page. Render venue contact and hours info using HOURS array (7 days Mon–Sun with open/close times and dayIndex). Use useState(todayIndex) initialized via useEffect calling new Date().getDay() to highlight today's row in the hours table. Display contact details with MapPinIcon, PhoneIcon, GlobeIcon, ClockIcon, NavigationIcon, ExternalLinkIcon, InfoIcon SVG components. Show a 'Get Directions' button with NavigationIcon and an external website link with ExternalLinkIcon. Highlight today's HOURS entry (matched via dayIndex) with a distinct active row style. Show open/closed status derived from current time vs today's hours.
As a frontend developer, implement the PlaceDetailAmenities section for the PlaceDetail page. Render ALL_AMENITIES array (8 items: parking/wifi/restrooms/food-court/atm/wheelchair/security plus additional) as filterable grid cards. Each amenity card shows an inline SVG icon, name, detail, category badge, and an available status indicator. Implement category filter tabs using useState(activeCategory) to filter cards by category strings (Transport, Connectivity, Facilities, Dining, Finance, Accessibility). Apply availability styling — cards with available:true get active color treatment. Show amenity count summary. Support a 'Show All' toggle via useState(showAll) revealing cards beyond an initial display limit.
As a frontend developer, implement the PlaceDetailReviews section for the PlaceDetail page. Render 5 REVIEWS (Arjun/AM/blue, Priya/PS/coral, Rohan/RI/teal, Divya/DN/purple, Karthik/KR/gold) each with initials avatar (avatarClass variants), date, rating, verified badge, visitType label, review text, and helpful count. Build a rating breakdown bar chart from BREAKDOWN array (5→1 star counts, max:48) as proportional fill bars. Display AVERAGE_RATING (4.3) and REVIEW_COUNT (98) aggregate header. Render StarIcon components with type='full'/'half'/'empty' variants. Implement filter tabs by rating using useState(activeFilter). Add a helpful button with useState(helpfulClicked) per review toggling count +1. Use useState(expanded) per review for 'Read more' truncation toggle.
As a frontend developer, implement the PlaceDetailVisitTiming section for the PlaceDetail page. Build an interactive heatmap grid of 7 DAYS × 17 HOURS (6AM–10PM via HOURS array) using CROWD_DATA object (per-day arrays of 0..1 values). Apply getCrowdColor() for cell background — a 4-segment color interpolation: blue (0–0.25, rgb 26,115,232), green (0.25–0.5, rgb 95,180,100), yellow (0.5–0.75, rgb 255,215,0), red (0.75–1.0, rgb 180,30,30). Use useState(selectedDay) to highlight the active day row. On cell hover, use useState(hoveredCell) to show a tooltip with formatHour() label and getCrowdLabel() text. Animate heatmap cell entrance via gsap stagger on useRef container using useCallback. Render 4 INSIGHTS cards (Quietest Day/Best Time/Peak Hours/Avoid) with iconBg/iconColor styling. Implement useEffect to auto-select today's day key.
As a frontend developer, implement the PlaceDetailDirections section for the PlaceDetail page. Render 4 TRANSPORT_OPTIONS (walk/12min/Nearby, bus/8min/Recommended, metro/5min/Fastest, cab/4min/Quick) as selectable cards using useState(activeTransport). Each card has an inline SVG icon (walking figure, bus rect, metro rect, cab path), type class (pdd-walk/pdd-bus/pdd-metro/pdd-cab), name, detail, duration, unit, and badge label. On transport card selection, use gsap to animate a route path SVG or step indicator into view via useRef(routeRef). Render a NavigationIcon polygon in the primary 'Get Directions' button and PinIcon for origin/destination markers. Include InfoIcon for estimated fare/time notes. Use useEffect to trigger gsap.fromTo() entrance stagger on TRANSPORT_OPTIONS cards on mount.
As a frontend developer, implement the PlaceDetailCTA section for the PlaceDetail page. Use IntersectionObserver on rootRef to trigger a gsap.to() stagger animation on all .pdcta-reveal elements (opacity:0,y:28 → opacity:1,y:0, duration:0.65) guarded by hasAnimated useRef flag. Render a primary 'Plan Visit' button with CalendarIcon SVG and a secondary 'Save to Favorites' toggle button with HeartIcon SVG (filled prop driven by useState(saved)). On save click, update useState(saveLabel) from 'Save to Favorites' to 'Saved!' and set saved:true. Render 3 TRUST_ITEMS (ShieldIcon/'Free cancellation', ClockIcon/'Real-time availability', UsersIcon/'2.4K visitors this week') as a trust badge row. Use useRef for rootRef, contentRef, btnRowRef.
As a frontend developer, implement the Footer section for the PlaceDetail page. Reuse or extend the Footer component from previous pages (Splash, Home, Search, Results, Map) if already built. Render quickLinks (Home/Search/Map/Notifications), exploreLinks (Splash/Results/Place Detail), and legalLinks (Privacy/Terms/Cookie) using AnimatedLink and AnimatedLegalLink components — each tracks useState(hovered) to animate a motion.span underline (scaleX:0→1, duration:0.3/0.25, ease:'easeOut'). Render 3 SocialIcon components (LinkedIn/Twitter/GitHub) from socialIcons array with paths length metadata. Apply motion.a whileHover scale/color transitions on social buttons via useState(hovered) per icon.
As a frontend developer, implement the NotificationsHeader section for the Notifications page. Build the header using useState for unreadCount (initialized to UNREAD_COUNT=7), markingRead, showToast, and toastExit. Use useRef for rootRef, titleRef, badgeRef, actionsRef, and toastTimer. Implement GSAP entrance timeline via gsap.context on rootRef with sequential fromTo animations: titleRef (opacity 0→1, y -18→0, duration 0.55), badgeRef (opacity 0→1, scale 0.5→1, back.out(1.8)), actionsRef (opacity 0→1, x 20→0). Implement handleMarkAllRead which triggers GSAP scale 0/opacity 0 on badgeRef (back.in(1.5)) then sets unreadCount to 0 and shows toast. Include CheckAllIcon, SettingsGearIcon, CheckCircleIcon SVG components. Manage toast auto-dismiss timer via toastTimer ref with toastExit state for exit animation.
As a frontend developer, implement the ResultsPlacesList section for the Results page. Renders a PLACES array of 8+ place objects (Central City Mall, Green Valley Park, Sunrise Hospital, University Campus, Shri Ganesh Temple, MedPlus Pharmacy, Metro Square Mall, Riverside Children's Park) each with id/name/category/area/distance/rating/crowd/crowdLevel/crowdLabel/isOpen/imageColor/icon/lat/lon properties. MAP_CENTER_LAT/LON constants (28.6139, 77.2090) and MAP_ZOOM=14 define map reference point. Each place card displays gradient imageColor background, crowdLevel badge (low/medium/high with color coding), star rating, distance chip, and isOpen status. Uses useRef and useEffect for scroll-triggered entrance animations. Crowd density shown as progress bar with percentage. Cards link to PlaceDetail page passing place id.
As a frontend developer, implement the NotificationsFilters section for the Notifications page. Render FILTER_TABS array (all/24, crowd/8, place/6, schedule/5, system/5) each with inline SVG icons and count badges using tabClass variants (nf-tab-all, nf-tab-crowd, nf-tab-place, nf-tab-schedule, nf-tab-system). Use useState for active tab id and sort dropdown open state. Render SORT_OPTIONS array (Newest First, Oldest First, Unread First, By Priority) in a dropdown toggled by ChevronDownIcon SVG. Include SearchIcon SVG for inline notification search input with useState for search query. Use useRef for scroll container and tab refs. Use useCallback for tab change and sort selection handlers. Apply useEffect to animate sliding indicator to active tab position.
As a frontend developer, implement the NotificationsEmptyState section for the Notifications page. Build a React Three Fiber Canvas with BellScene component using useRef for groupRef, ringRef, and glowRef. Implement useFrame animation loop: groupRef idle float via Math.sin(t*0.8)*0.08 on position.y and Math.sin(t*1.2)*0.06 on rotation.z; ringRef oscillation Math.sin(t*2.5)*0.12 on rotation.z; glowRef opacity pulse 0.12+Math.sin(t*1.5)*0.06. Build bell geometry from: outer glow sphere (sphereGeometry r=1.2, BackSide meshBasicMaterial #1A73E8), flared cylinder body (cylinderGeometry 0.72/0.88/1.1/48, metalness 0.55), dome top (sphereGeometry half-sphere), gold torus rim (torusGeometry #FFD700, metalness 0.9), orange clapper sphere, hanger cylinder, and 5 sparkle octahedron meshes at fixed positions. Use GSAP for text content entrance animation via useRef.
As a frontend developer, implement the NotificationsArchived section for the Notifications page. Render ARCHIVED_NOTIFICATIONS array of 5 items (Crowd Surge at City Mall/3 days ago, Green Valley Park Closed/5 days ago, Sunrise Hospital Added/1 week ago, Low Crowd at Downtown Plaza/1 week ago, Voice Assistant Updated/2 weeks ago) each with type (crowd/closed/info/system), tag pill, desc, and time. Use useState for collapsed/expanded section state toggled by ChevronDownIcon SVG. Implement per-item restore and delete actions using useState for local archived list with useCallback handlers. Include ArchiveIcon, RestoreIcon, TrashIcon, ClearIcon SVG components. Add 'Clear All' bulk action button. Render CARD_ICONS keyed by type (crowd/closed/info/system) as inline SVG elements.
As a frontend developer, implement the NotificationsSettings section for the Notifications page. Use useState for toggles object (DEFAULT_TOGGLES: crowdAlerts/true, placeUpdates/true, reminders/true, systemNotifications/false, sound/true, vibration/true), quietHours object (DEFAULT_QUIET: enabled/true, from '22:00', to '07:00'), and digest string (DEFAULT_DIGEST: 'daily'). Build toggle switches for each setting key with useCallback handler updating toggles via spread. Render BellIcon, CrowdIcon, PlaceIcon, ReminderIcon, SystemIcon, SoundIcon, VibrationIcon, MoonIcon, MailIcon, SaveIcon SVG components paired with their respective settings rows. Implement quiet hours time inputs bound to quietHours.from and quietHours.to with enabled toggle. Build digest frequency selector (daily/weekly/realtime) as radio or button group. Include save button with SaveIcon triggering confirmation feedback.
As a frontend developer, implement the ResultsPagination section for the Results page. Manages currentPage (useState, default 1) and perPage (useState, default 10) state. TOTAL_RESULTS=84 with PER_PAGE_OPTIONS array (10/25/50). totalPages computed as Math.ceil(84/perPage). getPageNumbers() generates smart page number arrays with ellipsis-start/ellipsis-end sentinel strings — shows 7 items max, collapsing middle or ends based on currentPage proximity to boundaries. handlePrev/handleNext clamp to [1, totalPages]. handlePerPageChange resets to page 1. Renders rp-perpage select dropdown, ChevronLeft/ChevronRight SVG nav buttons with disabled state when at boundaries, numbered page buttons with ellipsis spans, and a results range label (e.g., '1–10 of 84'). rp-btn-label text hidden on mobile.
As a frontend developer, implement the NotificationsAlertsList section for the Notifications page. Build OsmMapTile sub-component using latLngToTile(lat, lng, zoom=14) to compute x/y tile coordinates and construct OSM tile URL (https://tile.openstreetmap.org/{zoom}/{x}/{y}.png) rendered as img with onError hide fallback and map pin SVG overlay. Render ALERT_DATA array of 5 alerts (crowd-surge, place-update, schedule-reminder, system, and more) each with type badge (nal-badge-crowd/place), icon emoji, unread indicator, timestamp, message, expandable detail with detailMeta array, and OsmMapTile for geo-tagged alerts (mapLat/mapLng). Use useState for expanded alert id and read state per alert. Implement GSAP staggered card entrance animations via useRef and useEffect. Include 'View Details' href to /PlaceDetail per alert.
Find malls, hospitals, schools, and more with live crowd density — powered by real-time location data and voice assistance.
Click on building clusters to discover malls, hospitals, schools, temples, parks, and medical facilities near you. Each cluster reveals real-time crowd density.
Use your voice to find nearby malls, hospitals, parks, and more. Get real-time crowd density insights hands-free.
Quickly find malls, hospitals, parks, and more near you
Whether you are a student rushing between classes, a traveler exploring a new city, or a local planning your weekend — scenic-mall adapts to your needs.
Find nearby amenities like libraries, cafeterias, and study spots. Check crowd levels before heading out to plan your day efficiently and avoid long waits.
Quickly discover essential services — hospitals, malls, parks, and temples — in unfamiliar areas. Get real-time crowd info so you can explore comfortably.
Plan visits to your favorite spots at the right time. Use live crowd density data to avoid peak hours at malls, parks, and medical facilities.
scenic-mall combines real-time location data, voice assistance, and crowd intelligence so you always know where to go and when.
Find nearby malls, hospitals, schools, temples, and parks instantly using your live GPS data. Results update as you move through the city.
Speak naturally to search for places and get crowd information. Our AI-powered voice assistant understands context and delivers hands-free results.
See real-time crowd levels at any location before you visit. Color-coded indicators help you pick the best time for a comfortable experience.
Filter places by category, distance, crowd level, and ratings. Personalized suggestions learn your preferences over time for faster decisions.
Explore an interactive map with live pins showing nearby places and their crowd status. Tap any pin for instant details and navigation directions.
Find nearby malls, hospitals, parks, and more — all with live crowd density insights and voice-guided navigation. Start your smarter city exploration today.
No comments yet. Be the first!