diff --git a/src/components/platform/AnimatedDashboard.tsx b/src/components/platform/AnimatedDashboard.tsx new file mode 100644 index 0000000..7572119 --- /dev/null +++ b/src/components/platform/AnimatedDashboard.tsx @@ -0,0 +1,467 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { motion, AnimatePresence, useReducedMotion } from "framer-motion"; + +type ProductAsset = { + emoji: string; + name: string; + xStart: string; // Tailwind coordinate + yStart: string; // Tailwind coordinate + floatDelay: number; + floatDuration: number; +}; + +// Define products that float and participate in AI automation +const PRODUCT_ASSETS: ProductAsset[] = [ + { emoji: "🍎", name: "Apple", xStart: "left-[5%]", yStart: "top-[10%]", floatDelay: 0, floatDuration: 4 }, + { emoji: "🥛", name: "Milk", xStart: "right-[5%]", yStart: "top-[15%]", floatDelay: 0.5, floatDuration: 4.5 }, + { emoji: "🍞", name: "Bread", xStart: "left-[0%]", yStart: "top-[45%]", floatDelay: 0.8, floatDuration: 4.8 }, + { emoji: "🥬", name: "Spinach", xStart: "right-[2%]", yStart: "top-[50%]", floatDelay: 1.2, floatDuration: 5.2 }, + { emoji: "🏷️", name: "Price Tag", xStart: "left-[8%]", yStart: "bottom-[12%]", floatDelay: 1.5, floatDuration: 4.2 }, + { emoji: "📲", name: "QR Code", xStart: "right-[8%]", yStart: "bottom-[15%]", floatDelay: 2, floatDuration: 4.6 }, +]; + +export function AnimatedDashboard() { + const reduce = useReducedMotion(); + + // Animation states + const [animatingIndex, setAnimatingIndex] = useState(0); + const [stage, setStage] = useState<"idle" | "flying" | "scanning" | "updating" | "notifying">("idle"); + const [itemsCount, setItemsCount] = useState(142); + const [ordersCount, setOrdersCount] = useState(8); + + useEffect(() => { + if (reduce) return; + + const cycle = setInterval(() => { + // 1. Start Fly-in phase + setStage("flying"); + + // 2. Scan phase: Product reaches center, trigger laser scan + const scanTimer = setTimeout(() => { + setStage("scanning"); + }, 900); + + // 3. Update dashboard values (counter, green success pulse) + const updateTimer = setTimeout(() => { + setStage("updating"); + + // Update specific counters based on what product is processed + if (animatingIndex === 0) { + setItemsCount((c) => c + 1); + } else if (animatingIndex === 1) { + setOrdersCount((c) => c + 1); + } + }, 1400); + + // 4. Micro-notification appears + const notifyTimer = setTimeout(() => { + setStage("notifying"); + }, 1800); + + // 5. Clear notification, return to idle + const idleTimer = setTimeout(() => { + setStage("idle"); + setAnimatingIndex((prev) => (prev + 1) % 4); // Cycle through the first 4 products + }, 5200); + + return () => { + clearTimeout(scanTimer); + clearTimeout(updateTimer); + clearTimeout(notifyTimer); + clearTimeout(idleTimer); + }; + }, 8000); // Complete animation cycle every 8 seconds + + return () => clearInterval(cycle); + }, [animatingIndex, reduce]); + + // Floating variants for the idle products surrounding the dashboard + const floatVariant = (delay: number, duration: number) => ({ + animate: { + y: [0, -10, 0], + rotate: [-3, 3, -3], + scale: [1, 1.02, 1], + transition: { + duration, + repeat: Infinity, + ease: "easeInOut", + delay, + }, + }, + }); + + // Curved flight coordinates relative to the absolute dashboard layout + // Product index maps to original coordinates: + // index 0 (Apple): left-5%, top-10% (x: 5%, y: 10%) -> center (x: 50%, y: 45%) + const flightPaths = [ + { x: ["5%", "25%", "50%"], y: ["10%", "20%", "45%"] }, // Apple + { x: ["95%", "75%", "50%"], y: ["15%", "25%", "45%"] }, // Milk + { x: ["0%", "20%", "50%"], y: ["45%", "40%", "45%"] }, // Bread + { x: ["98%", "78%", "50%"], y: ["50%", "45%", "45%"] }, // Spinach + ]; + + return ( +
+ {/* ── Background Glow ── */} +
+ + {/* ── 1. Floating Product Assets (Around Dashboard) ── */} + {PRODUCT_ASSETS.map((product, idx) => { + // Hide specific products on tablet/mobile screens + let responsiveClass = "absolute z-20 "; + if (idx === 2 || idx === 3) { + responsiveClass += "hidden lg:block"; // Only desktop + } else if (idx === 0 || idx === 1 || idx === 4 || idx === 5) { + responsiveClass += "hidden md:block"; // Desktop & Tablet + } + + const isCurrentlyAnimating = stage !== "idle" && animatingIndex === idx; + + return ( + +
+ {product.emoji} +
+
+ ); + })} + + {/* ── 2. Flying Product Scan Asset ── */} + + {stage === "flying" && animatingIndex < 4 && ( + + {PRODUCT_ASSETS[animatingIndex].emoji} + + )} + + + {/* ── 3. AI Processing Particle Trails ── */} + {stage === "flying" && animatingIndex < 4 && ( + <> + {[0, 1, 2].map((particleIdx) => ( + + ))} + + )} + + {/* ── 4. Slide-in Micro-Notifications ── */} + + {stage === "notifying" && ( + + + + {animatingIndex === 0 && "Apple Catalog Listing Synced"} + {animatingIndex === 1 && "Milk Delivery Stock Updated"} + {animatingIndex === 2 && "Bread Pricing Configuration Live"} + {animatingIndex === 3 && "Spinach Category Catalog Indexed"} + + + )} + + + {/* ── 5. Main Dashboard Canvas ── */} +
+ {/* Ambient Success Pulse Border */} + + + + {/* Ground shadow */} + + + {/* Main dashboard window */} + + + {/* Top window bar chrome */} + + + + + + + + {/* Sidebar navigation */} + + + + + + + + + {/* QR Ordering live badge */} + + + + QR ACTIVE + + + + {/* Loyalty active badge */} + + + LOYALTY + + + + {/* ── KPI Chips ── */} + {/* KPI 1: Inventory Items */} + + + ITEMS + + {/* Animate number change */} + + {itemsCount} + + + {/* Micro pulse indicator */} + + + + {/* KPI 2: Sales Counter */} + + + SALES + + ₹18,240 + + + + {/* KPI 3: Orders Counter */} + + + ORDERS + + {/* Animate orders increase */} + + {ordersCount} + + + + + + {/* ── Chart Panel (Middle Area) ── */} + + + + + {/* Gridlines */} + + + + {/* Dynamic line graph */} + + + {/* Pulse node */} + + + + {/* ── Mini Bar Chart ── */} + + + + {[ + { x: 314, h: 34, c: "#DDD0F4" }, + { x: 332, h: 52, c: "#B99BEC" }, + { x: 350, h: 44, c: "#9B78E4" }, + { x: 368, h: 66, c: "#6330D6" }, + ].map((b, bIdx) => { + // If index 2 product (price/pricing) updates, scale the heights briefly + const isTargetBar = bIdx === 2 || bIdx === 3; + const multiplier = stage === "updating" && animatingIndex === 2 && isTargetBar ? 1.25 : 1; + const barHeight = b.h * multiplier; + + return ( + + ); + })} + + + {/* ── Floating order card top right (floating) ── */} + + + + + + + + + {/* ── Floating live stock status bottom left (floating) ── */} + + + + + + + + {/* ── Purple AI Laser Scanning Beam ── */} + {stage === "scanning" && ( + + )} + +
+
+ ); +} diff --git a/src/components/platform/ProductFeatureGrid.tsx b/src/components/platform/ProductFeatureGrid.tsx index 3e30e7b..9ed8273 100644 --- a/src/components/platform/ProductFeatureGrid.tsx +++ b/src/components/platform/ProductFeatureGrid.tsx @@ -3,8 +3,7 @@ import { useRef } from "react"; import { motion, useReducedMotion, useScroll, useTransform } from "framer-motion"; import { MaterialIcon } from "@/components/ui/MaterialIcon"; -import { DashboardMockup } from "@/components/platform/DeviceShowcase"; -import { ConsumerShowcase } from "@/components/platform/ConsumerShowcase"; +import { AnimatedDashboard } from "@/components/platform/AnimatedDashboard"; import { fadeUp, staggerContainer, staggerCards, viewport, viewport20 } from "@/lib/animations"; export type ProductFeature = { @@ -137,7 +136,7 @@ export function ProductFeatureGrid({ "radial-gradient(circle at 50% 40%, rgba(99,48,214,0.16), transparent 62%)", }} /> - {isPhone ? : } +