Spaces:
Running
Running
| "use client"; | |
| import React, { useState, useEffect } from "react"; | |
| import { db, auth } from "@/lib/firebase"; | |
| import { collection, onSnapshot, query, orderBy, limit } from "firebase/firestore"; | |
| import Link from "next/link"; | |
| import { | |
| AreaChart, | |
| Area, | |
| XAxis, | |
| YAxis, | |
| CartesianGrid, | |
| Tooltip, | |
| ResponsiveContainer, | |
| BarChart, | |
| Bar, | |
| Cell | |
| } from 'recharts'; | |
| import { | |
| Package, | |
| Users, | |
| ShoppingCart, | |
| LayoutDashboard | |
| } from 'lucide-react'; | |
| import { motion } from 'framer-motion'; | |
| const dummyData = [ | |
| { name: 'Lun', sales: 4000, products: 2400 }, | |
| { name: 'Mar', sales: 3000, products: 1398 }, | |
| { name: 'Mie', sales: 2000, products: 9800 }, | |
| { name: 'Jue', sales: 2780, products: 3908 }, | |
| { name: 'Vie', sales: 1890, products: 4800 }, | |
| { name: 'Sab', sales: 2390, products: 3800 }, | |
| { name: 'Dom', sales: 3490, products: 4300 }, | |
| ]; | |
| export default function Dashboard() { | |
| const [stats, setStats] = useState({ products: 0, clients: 0, salesCount: 0, revenue: 0 }); | |
| useEffect(() => { | |
| const unsubProducts = onSnapshot(collection(db, "products"), (snap) => setStats((p) => ({ ...p, products: snap.size }))); | |
| const unsubClients = onSnapshot(collection(db, "clients"), (snap) => setStats((p) => ({ ...p, clients: snap.size }))); | |
| const unsubSales = onSnapshot(collection(db, "sales"), (snap) => { | |
| let rev = 0; | |
| snap.forEach((doc) => rev += doc.data().total || 0); | |
| setStats((p) => ({ ...p, salesCount: snap.size, revenue: rev })); | |
| }); | |
| return () => { unsubProducts(); unsubClients(); unsubSales(); }; | |
| }, []); | |
| return ( | |
| <div className="min-h-screen bg-[#0f172a] text-white p-10"> | |
| <header className="flex justify-between items-center mb-16"> | |
| <div> | |
| <h1 className="text-6xl font-black tracking-tighter italic bg-gradient-to-br from-white to-gray-500 bg-clip-text text-transparent"> | |
| ERP / NEXUS | |
| </h1> | |
| <p className="text-gray-500 font-bold mt-2 uppercase text-xs tracking-widest">Plataforma de Control Empresarial Inteligente</p> | |
| </div> | |
| <div className="flex border border-white/10 rounded-2xl p-2 backdrop-blur-md bg-white/5"> | |
| <div className="px-4 py-2 bg-blue-600 rounded-xl text-xs font-black uppercase">En Vivo</div> | |
| <div className="px-4 py-2 text-xs font-bold text-gray-500">Global</div> | |
| </div> | |
| </header> | |
| {/* Stats Table */} | |
| <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16"> | |
| <StatCard title="Inventario" value={stats.products} icon={<Package />} color="from-blue-600" /> | |
| <StatCard title="Staff Activo" value={stats.clients} icon={<Users />} color="from-purple-600" /> | |
| <StatCard title="Ventas Mes" value={stats.salesCount} icon={<ShoppingCart />} color="from-orange-600" /> | |
| <StatCard title="Ingresos" value={`$${stats.revenue.toLocaleString()}`} icon={<LayoutDashboard />} color="from-emerald-600" /> | |
| </div> | |
| <div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| {/* Advanced Chart */} | |
| <div className="lg:col-span-2 bg-white/5 border border-white/10 rounded-[3rem] p-10 h-[450px]"> | |
| <h2 className="text-xl font-black italic uppercase tracking-widest mb-10 text-gray-400">Rendimiento Mensual / <span className="text-white">Revenue</span></h2> | |
| <ResponsiveContainer width="100%" height="70%"> | |
| <AreaChart data={dummyData}> | |
| <defs> | |
| <linearGradient id="colorSales" x1="0" y1="0" x2="0" y2="1"> | |
| <stop offset="5%" stopColor="#3b82f6" stopOpacity={0.3}/> | |
| <stop offset="95%" stopColor="#3b82f6" stopOpacity={0}/> | |
| </linearGradient> | |
| </defs> | |
| <Tooltip | |
| contentStyle={{ backgroundColor: '#1e293b', border: 'none', borderRadius: '16px', fontSize: '12px' }} | |
| itemStyle={{ color: '#fff' }} | |
| /> | |
| <Area type="monotone" dataKey="sales" stroke="#3b82f6" strokeWidth={4} fillOpacity={1} fill="url(#colorSales)" /> | |
| </AreaChart> | |
| </ResponsiveContainer> | |
| </div> | |
| {/* Inventory Widget */} | |
| <div className="bg-white/5 border border-white/10 rounded-[3rem] p-10 relative overflow-hidden group"> | |
| <div className="absolute top-0 right-0 p-8 text-6xl opacity-5 group-hover:opacity-10 transition-opacity font-black italic">DATA</div> | |
| <h2 className="text-xl font-black italic uppercase tracking-widest mb-10 text-gray-400">Distribución / <span className="text-white">Stock</span></h2> | |
| <div className="space-y-6"> | |
| <ProgressWidget label="Electrónicos" value={78} color="bg-blue-500" /> | |
| <ProgressWidget label="Mobiliario" value={45} color="bg-purple-500" /> | |
| <ProgressWidget label="Insumos" value={92} color="bg-emerald-500" /> | |
| <ProgressWidget label="Servicios" value={23} color="bg-orange-500" /> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function StatCard({ title, value, icon, color }: any) { | |
| return ( | |
| <div className="bg-white/5 border border-white/10 rounded-[2.5rem] p-8 backdrop-blur-xl relative group cursor-pointer hover:bg-white/10 transition-all"> | |
| <div className={`absolute top-0 left-0 w-full h-1 bg-gradient-to-r ${color} to-transparent opacity-0 group-hover:opacity-100 transition-opacity`}></div> | |
| <div className="flex flex-col gap-4"> | |
| <div className="w-12 h-12 bg-white/10 rounded-2xl flex items-center justify-center text-blue-400">{icon}</div> | |
| <p className="text-[10px] font-black uppercase tracking-[0.2em] text-gray-500">{title}</p> | |
| <p className="text-4xl font-black italic tracking-tighter">{value}</p> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function ProgressWidget({ label, value, color }: any) { | |
| return ( | |
| <div className="space-y-2"> | |
| <div className="flex justify-between text-[10px] font-black uppercase tracking-widest"> | |
| <span>{label}</span> | |
| <span className="text-gray-500">{value}%</span> | |
| </div> | |
| <div className="w-full h-1.5 bg-white/5 rounded-full overflow-hidden"> | |
| <motion.div | |
| initial={{ width: 0 }} | |
| animate={{ width: `${value}%` }} | |
| className={`h-full ${color}`} | |
| /> | |
| </div> | |
| </div> | |
| ); | |
| } | |