NEXUS / app /page.tsx
dimensionalpulsar's picture
Upload 32 files
8e723d7 verified
"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>
);
}