Spaces:
Running
Running
| "use client"; | |
| import React, { useState } from "react"; | |
| import { motion, AnimatePresence } from "framer-motion"; | |
| import { | |
| Network, | |
| Target, | |
| Rocket, | |
| Shield, | |
| Users, | |
| Zap, | |
| Heart, | |
| Briefcase | |
| } from "lucide-react"; | |
| const mindMapData = [ | |
| { id: "root", label: "Corporación ERP", icon: Network, color: "text-blue-400", sub: ["mision", "vision", "valores"] }, | |
| { id: "mision", label: "Misión", icon: Target, color: "text-purple-400", sub: ["digitalizar", "automatizar"] }, | |
| { id: "vision", label: "Visión 2030", icon: Rocket, color: "text-orange-400", sub: ["global", "ia"] }, | |
| { id: "valores", label: "Valores", icon: Shield, color: "text-emerald-400", sub: ["etica", "calidad"] }, | |
| { id: "digitalizar", label: "Digitalización", icon: Zap, color: "text-yellow-400", parent: "mision" }, | |
| { id: "automatizar", label: "Automatización", icon: Heart, color: "text-pink-400", parent: "mision" }, | |
| { id: "global", label: "Expansión Global", icon: Briefcase, color: "text-blue-500", parent: "vision" }, | |
| { id: "ia", label: "IA Avanzada", icon: Rocket, color: "text-indigo-400", parent: "vision" }, | |
| ]; | |
| export default function MindMapPage() { | |
| const [activeNode, setActiveNode] = useState("root"); | |
| const currentNode = mindMapData.find(n => n.id === activeNode) || mindMapData[0]; | |
| const children = mindMapData.filter(n => currentNode.sub?.includes(n.id)); | |
| const parent = mindMapData.find(n => n.id === currentNode.parent); | |
| return ( | |
| <div className="p-10 min-h-screen relative flex items-center justify-center overflow-hidden"> | |
| <div className="absolute top-10 left-10"> | |
| <h1 className="text-4xl font-black italic mb-2 tracking-tighter">MIND / MAP</h1> | |
| <p className="text-gray-500 font-bold uppercase text-[10px] tracking-widest">ADN de la Organización</p> | |
| </div> | |
| <AnimatePresence mode="wait"> | |
| <motion.div | |
| key={activeNode} | |
| initial={{ opacity: 0, scale: 0.8 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 1.2 }} | |
| className="relative flex flex-col items-center" | |
| > | |
| {/* Main Node */} | |
| <div className="relative z-20"> | |
| <NodeUI node={currentNode} size="large" /> | |
| {/* Parent Link */} | |
| {parent && ( | |
| <button | |
| onClick={() => setActiveNode(parent.id)} | |
| className="absolute -top-32 left-1/2 -translate-x-1/2 px-4 py-2 bg-white/5 border border-white/10 rounded-full text-[10px] font-black uppercase text-gray-500 hover:text-white hover:bg-white/10 transition-all border-dashed" | |
| > | |
| ↑ Subir a {parent.label} | |
| </button> | |
| )} | |
| </div> | |
| {/* Children Nodes */} | |
| {children.length > 0 && ( | |
| <div className="mt-40 flex gap-20 relative"> | |
| {children.map((child, i) => ( | |
| <div key={child.id} className="relative group"> | |
| <motion.div | |
| initial={{ y: 20, opacity: 0 }} | |
| animate={{ y: 0, opacity: 1 }} | |
| transition={{ delay: i * 0.1 }} | |
| onClick={() => setActiveNode(child.id)} | |
| className="cursor-pointer" | |
| > | |
| <NodeUI node={child} size="medium" /> | |
| </motion.div> | |
| {/* Line */} | |
| <div className="absolute -top-24 left-1/2 -translate-x-1/2 w-px h-24 bg-gradient-to-t from-white/20 to-transparent"></div> | |
| </div> | |
| ))} | |
| </div> | |
| )} | |
| </motion.div> | |
| </AnimatePresence> | |
| <div className="absolute bottom-10 right-10 text-right text-[10px] text-gray-700 font-bold uppercase tracking-widest leading-loose"> | |
| Navegación Interactiva<br/> | |
| Selecciona un nodo para profundizar<br/> | |
| Basado en Core-Business Pillars | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function NodeUI({ node, size }: { node: any, size: "large" | "medium" }) { | |
| const Icon = node.icon; | |
| return ( | |
| <div className={` | |
| flex flex-col items-center justify-center rounded-[3rem] border backdrop-blur-3xl shadow-2xl group transition-all | |
| ${size === 'large' ? 'w-64 h-64 bg-blue-600/10 border-blue-500/40' : 'w-48 h-48 bg-white/5 border-white/10 hover:border-white/30 hover:bg-white/10'} | |
| `}> | |
| <Icon size={size === 'large' ? 64 : 40} className={`${node.color} mb-6 group-hover:scale-110 transition-transform`} /> | |
| <span className={`font-black uppercase tracking-tighter text-center px-4 ${size === 'large' ? 'text-2xl' : 'text-sm text-gray-400 group-hover:text-white transition-colors'}`}> | |
| {node.label} | |
| </span> | |
| {node.sub && ( | |
| <span className="mt-4 text-[8px] font-black text-blue-500/60 uppercase group-hover:text-blue-400 transition-colors"> | |
| Expandible + | |
| </span> | |
| )} | |
| </div> | |
| ); | |
| } | |