feat: setup docker and push project to remote

This commit is contained in:
Erik Silva
2026-01-20 13:44:32 -03:00
parent 45bac0c990
commit 261fd429d5
74 changed files with 12876 additions and 101 deletions

View File

@@ -0,0 +1,278 @@
"use client";
import React from "react";
import { motion } from "framer-motion";
import {
FileText,
Plus,
TrendingUp,
Eye,
Calendar,
ChevronRight,
ArrowUpRight,
ArrowRight,
} from "lucide-react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Sidebar } from "@/components/Sidebar";
type Organization = {
id: string;
name: string;
logoUrl: string | null;
primaryColor: string;
};
type UserType = {
id: string;
name: string | null;
email: string;
role: string;
};
type DashboardStats = {
docCount: number;
viewCount: number;
downloadCount: number;
recentDocs: any[];
};
export default function DashboardClient({
user,
organization,
stats,
}: {
user: UserType;
organization: Organization;
stats: DashboardStats;
}) {
const primaryColor = organization.primaryColor || "#2563eb";
const formatDate = (date: Date) => {
return new Date(date).toLocaleDateString("pt-BR", {
day: "2-digit",
month: "short",
});
};
return (
<div className="min-h-screen bg-white flex">
<Sidebar user={user} organization={organization} />
{/* Main Content Area */}
<main className="flex-1 overflow-y-auto">
{/* Top Banner / Hero - Integrated Background */}
<div className="relative border-b border-slate-100 bg-slate-50/40 p-8 lg:p-10">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-6">
<div>
<div className="flex items-center gap-2 mb-2">
<span className="px-2 py-0.5 bg-white border border-slate-200 rounded-full text-[9px] font-bold uppercase tracking-[0.1em] text-slate-500">Overview Panel</span>
</div>
<h2 className="text-2xl font-black text-slate-900 tracking-tight mb-1">Dashboard</h2>
<p className="text-sm text-slate-500 font-medium">
Bem-vindo, Administrador <span className="text-slate-900">{user.name?.split(' ')[0] || "Administrador"}</span>.
</p>
</div>
<div className="flex items-center gap-3">
<Button
asChild
style={{ backgroundColor: primaryColor }}
className="h-10 px-6 rounded-lg font-bold text-xs shadow-none hover:opacity-90 active:scale-95 transition-all text-white"
>
<Link href="/dashboard/documentos?upload=true">
<Plus size={18} className="mr-2 stroke-[3]" />
Novo Documento
</Link>
</Button>
</div>
</div>
{/* Faded accent circle */}
<div
className="absolute top-0 right-0 w-[300px] h-[300px] rounded-full blur-[80px] opacity-[0.03] pointer-events-none"
style={{ backgroundColor: primaryColor }}
/>
</div>
<div className="p-8 lg:p-10 w-full">
{/* Stats Grid - Large and minimalist */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-5 mb-10">
<motion.div initial={{ opacity: 0, y: 15 }} animate={{ opacity: 1, y: 0 }}>
<div className="group relative p-5 rounded-[20px] bg-slate-50 hover:bg-white border-2 border-transparent hover:border-slate-100 transition-all duration-500">
<div className="flex flex-col gap-3.5">
<div className="flex items-center justify-between">
<div className="w-10 h-10 rounded-lg bg-white flex items-center justify-center text-slate-800 border border-slate-100 group-hover:border-blue-100 transition-colors">
<FileText size={20} className="stroke-[2]" />
</div>
<div className="p-1 rounded-full bg-blue-50 text-blue-600">
<ArrowUpRight size={14} />
</div>
</div>
<div>
<p className="text-[9px] font-bold text-slate-400 uppercase tracking-widest mb-0.5">Total de Documentos</p>
<h3 className="text-2xl font-black text-slate-900">{stats.docCount}</h3>
</div>
</div>
</div>
</motion.div>
<motion.div initial={{ opacity: 0, y: 15 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.1 }}>
<div className="group relative p-5 rounded-[20px] bg-slate-50 hover:bg-white border-2 border-transparent hover:border-slate-100 transition-all duration-500">
<div className="flex flex-col gap-3.5">
<div className="flex items-center justify-between">
<div className="w-10 h-10 rounded-lg bg-white flex items-center justify-center text-slate-800 border border-slate-100 group-hover:border-green-100 transition-colors">
<Eye size={20} className="stroke-[2]" />
</div>
<div className="p-1 rounded-full bg-green-50 text-green-600">
<ArrowUpRight size={14} />
</div>
</div>
<div>
<p className="text-[9px] font-bold text-slate-400 uppercase tracking-widest mb-0.5">Visualizações Totais</p>
<h3 className="text-2xl font-black text-slate-900">{stats.viewCount.toLocaleString()}</h3>
</div>
</div>
</div>
</motion.div>
<motion.div initial={{ opacity: 0, y: 15 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.2 }}>
<div className="group relative p-5 rounded-[20px] bg-slate-50 hover:bg-white border-2 border-transparent hover:border-slate-100 transition-all duration-500">
<div className="flex flex-col gap-3.5">
<div className="flex items-center justify-between">
<div className="w-10 h-10 rounded-lg bg-white flex items-center justify-center text-slate-800 border border-slate-100 group-hover:border-purple-100 transition-colors">
<TrendingUp size={20} className="stroke-[2]" />
</div>
<div className="p-1 rounded-full bg-purple-50 text-purple-600">
<ArrowUpRight size={14} />
</div>
</div>
<div>
<p className="text-[9px] font-bold text-slate-400 uppercase tracking-widest mb-0.5">Downloads Totais</p>
<h3 className="text-2xl font-black text-slate-900">{stats.downloadCount.toLocaleString()}</h3>
</div>
</div>
</div>
</motion.div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8">
{/* Recent Documents Table - More integrated */}
<motion.div initial={{ opacity: 0, y: 15 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.3 }} className="lg:col-span-8">
<div className="flex items-center justify-between mb-4 px-1">
<h3 className="text-lg font-black text-slate-900 tracking-tight">Atividade Recente</h3>
<Link href="/dashboard/documentos" className="group flex items-center gap-2 text-[9px] font-bold uppercase tracking-widest text-slate-400 hover:text-slate-900 transition-colors">
Ver Todos <ArrowRight size={12} className="group-hover:translate-x-0.5 transition-transform" />
</Link>
</div>
<div className="bg-white rounded-[24px] border-2 border-slate-100 overflow-hidden">
{stats.recentDocs.length === 0 ? (
<div className="p-14 text-center">
<div className="w-14 h-14 bg-slate-50 rounded-full flex items-center justify-center mx-auto mb-3">
<FileText size={24} className="text-slate-300" />
</div>
<p className="text-slate-500 font-medium mb-4 text-sm">Nenhum documento encontrado.</p>
<Button asChild variant="outline" className="rounded-lg border-2 font-bold px-6 h-9 text-[10px] uppercase tracking-widest">
<Link href="/dashboard/documentos/novo">Começar Agora</Link>
</Button>
</div>
) : (
<div className="divide-y-2 divide-slate-50">
{stats.recentDocs.map((doc) => (
<Link
key={doc.id}
href={`/dashboard/documentos/${doc.id}`}
className="flex items-center gap-4 py-3.5 px-6 hover:bg-slate-50/50 transition-all group"
>
<div className="w-10 h-10 rounded-lg bg-slate-50 group-hover:bg-white border-2 border-transparent group-hover:border-slate-100 flex items-center justify-center transition-all shrink-0">
<FileText size={18} className="text-slate-500 group-hover:text-slate-900 transition-colors" />
</div>
<div className="flex-1 min-w-0">
<h4 className="font-black text-slate-900 group-hover:text-blue-600 transition-colors truncate mb-0.5 text-sm">{doc.title}</h4>
<div className="flex items-center gap-3 text-[9px] font-bold text-slate-400 uppercase tracking-widest">
<span>{doc.folder?.name || "Sem categoria"}</span>
<span className="w-1 h-1 rounded-full bg-slate-200" />
<span>{formatDate(doc.createdAt)}</span>
</div>
</div>
<div className="text-right shrink-0">
<div className="flex items-center gap-2 text-slate-400 group-hover:text-slate-900 transition-colors">
<span className="text-[10px] font-bold uppercase tracking-widest">Detalhes</span>
<ChevronRight size={14} className="stroke-[3]" />
</div>
</div>
</Link>
))}
</div>
)}
</div>
</motion.div>
{/* Summary Column */}
<motion.div initial={{ opacity: 0, x: 20 }} animate={{ opacity: 1, x: 0 }} transition={{ delay: 0.4 }} className="lg:col-span-4 space-y-6">
<div className="bg-slate-900 rounded-[24px] p-6 text-white relative overflow-hidden group">
<div className="relative z-10">
<div className="w-10 h-10 bg-white/10 rounded-lg flex items-center justify-center mb-4">
<Calendar size={20} className="text-white" />
</div>
<h4 className="text-xl font-black tracking-tight mb-1">Status do Portal</h4>
<p className="text-white/60 text-xs font-medium leading-relaxed mb-6">
O portal está online e sincronizado com os últimos envios de documentos.
</p>
<Button variant="ghost" className="w-full bg-white/10 hover:bg-white/20 text-white font-bold text-[10px] uppercase tracking-widest h-10 rounded-lg border-none">
Ver Log de Atividades
</Button>
</div>
<div className="absolute -right-4 -bottom-4 w-32 h-32 bg-white/5 rounded-full blur-2xl group-hover:scale-150 transition-transform duration-700" />
</div>
<div className="bg-white border-2 border-slate-100 rounded-[24px] p-6">
<h4 className="text-base font-black text-slate-900 tracking-tight mb-4">Informações Rápidas</h4>
<div className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Organização</span>
<span className="text-xs font-black text-slate-900">{organization.name}</span>
</div>
<div className="h-px bg-slate-100" />
<div className="flex items-center justify-between">
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Seu Perfil</span>
<span className="text-xs font-black text-slate-900 uppercase tracking-tighter">{user.role}</span>
</div>
<div className="h-px bg-slate-100" />
<div className="flex items-center justify-between">
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Data</span>
<span className="text-xs font-black text-slate-900">{new Date().toLocaleDateString('pt-BR')}</span>
</div>
</div>
</div>
</motion.div>
</div>
</div>
</main>
</div>
);
}
function Users(props: any) {
return (
<svg
{...props}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
<circle cx="9" cy="7" r="4" />
<path d="M22 21v-2a4 4 0 0 0-3-3.87" />
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
</svg>
)
}