205 lines
11 KiB
JavaScript
205 lines
11 KiB
JavaScript
import React from 'react';
|
|
import {
|
|
ArrowRightLeft,
|
|
CheckCircle2,
|
|
AlertCircle,
|
|
Settings,
|
|
BarChart3,
|
|
History,
|
|
MessageSquare,
|
|
FileText
|
|
} from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { useConciliacaoV2 } from '../../hooks/useConciliacaoV2';
|
|
import { TransacoesConciliadasView } from './TransacoesConciliadasView';
|
|
import { TransacoesNaoCategorizadasView } from './TransacoesNaoCategorizadasView';
|
|
import { GerenciamentoView } from './GerenciamentoView';
|
|
import { ExtratoCompletoView } from './ExtratoCompletoView';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
const ActivityLog = ({ isOpen, onClose }) => {
|
|
if (!isOpen) return null;
|
|
|
|
return (
|
|
<div className="fixed inset-y-0 right-0 w-80 bg-white dark:bg-[#0f172a]/95 backdrop-blur-2xl border-l border-slate-200 dark:border-slate-800 shadow-2xl z-50 animate-in slide-in-from-right duration-500">
|
|
<div className="p-6 h-full flex flex-col">
|
|
<div className="flex items-center justify-between mb-8">
|
|
<h3 className="font-bold flex items-center gap-2 uppercase tracking-widest text-[10px] text-slate-500 dark:text-slate-400">
|
|
<History className="w-4 h-4 text-blue-500" /> Atividade (Buzz)
|
|
</h3>
|
|
<Button variant="ghost" size="sm" onClick={onClose} className="text-slate-500 hover:text-slate-900 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-slate-800">Fechar</Button>
|
|
</div>
|
|
|
|
<div className="flex-1 -mr-2 pr-4 overflow-y-auto">
|
|
<div className="space-y-6">
|
|
{[
|
|
{ user: 'Ana (CFO)', action: 'Conciliação automática', target: 'CONC-1002', time: '10 min atrás', color: 'text-blue-500' },
|
|
{ user: 'Bruno', action: 'Criou nova regra', target: 'REGRA-1045', time: '1h atrás', color: 'text-purple-500' },
|
|
].map((log, i) => (
|
|
<div key={i} className="flex gap-4 group">
|
|
<div className="mt-1 w-2 h-2 rounded-full bg-slate-200 dark:bg-slate-800 group-hover:bg-blue-500 transition-colors shrink-0" />
|
|
<div>
|
|
<p className="text-xs font-bold text-slate-900 dark:text-slate-200">{log.user}</p>
|
|
<p className="text-xs text-slate-500 mt-0.5">{log.action} <span className={log.color}>{log.target}</span></p>
|
|
<p className="text-[9px] text-slate-600 dark:text-slate-500 mt-1 uppercase font-bold tracking-tighter">{log.time}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-auto pt-6 border-t border-slate-200 dark:border-slate-800 font-inter">
|
|
<div className="bg-slate-100/50 dark:bg-slate-900/50 p-3 rounded-xl border border-slate-200 dark:border-slate-800">
|
|
<p className="text-[10px] text-slate-500 font-bold mb-2 uppercase italic tracking-widest">"Buzz" - Chat Interno</p>
|
|
<div className="flex gap-2 items-center">
|
|
<input type="text" placeholder="Escreva um comentário..." className="flex-1 bg-transparent border-none text-[11px] text-slate-900 dark:text-white outline-none placeholder:text-slate-400 dark:placeholder:text-slate-700" />
|
|
<MessageSquare className="w-3.5 h-3.5 text-slate-400 dark:text-slate-600 hover:text-blue-500 cursor-pointer" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const ConciliacaoView = ({ initialView }) => {
|
|
console.log('[ConciliacaoView] ========== COMPONENTE RENDERIZADO ==========');
|
|
console.log('[ConciliacaoView] Timestamp:', new Date().toISOString());
|
|
console.log('[ConciliacaoView] Cache Buster: v1.0.1 - Force Refresh');
|
|
console.log('[ConciliacaoView] InitialView prop:', initialView);
|
|
|
|
let state, actions;
|
|
try {
|
|
console.log('[ConciliacaoView] Chamando useConciliacaoV2(initialView)...');
|
|
const hookResult = useConciliacaoV2(initialView);
|
|
console.log('[ConciliacaoView] Hook retornou:', hookResult);
|
|
|
|
state = hookResult?.state;
|
|
actions = hookResult?.actions;
|
|
|
|
console.log('[ConciliacaoView] Hook executado com sucesso');
|
|
console.log('[ConciliacaoView] State:', state);
|
|
console.log('[ConciliacaoView] Actions:', actions);
|
|
} catch (error) {
|
|
console.error('[ConciliacaoView] ========== ERRO AO EXECUTAR HOOK ==========');
|
|
console.error('[ConciliacaoView] Erro:', error);
|
|
console.error('[ConciliacaoView] Stack:', error.stack);
|
|
// Não lançar erro para não quebrar a UI, mas logar tudo
|
|
}
|
|
|
|
const activeSubView = state?.activeSubView || 'conciliadas';
|
|
const isLoading = state?.isLoading !== undefined ? state.isLoading : true;
|
|
|
|
console.log('[ConciliacaoView] Estado atual:', {
|
|
activeSubView,
|
|
isLoading,
|
|
hasState: !!state,
|
|
hasActions: !!actions,
|
|
caixasCount: state?.caixas?.length || 0,
|
|
categoriasCount: state?.categorias?.length || 0
|
|
});
|
|
|
|
const [isBuzzOpen, setIsBuzzOpen] = React.useState(false);
|
|
|
|
// Log quando o componente é atualizado
|
|
React.useEffect(() => {
|
|
console.log('[ConciliacaoView] Componente montado/atualizado');
|
|
console.log('[ConciliacaoView] isLoading:', isLoading);
|
|
console.log('[ConciliacaoView] activeSubView:', activeSubView);
|
|
}, [isLoading, activeSubView]);
|
|
|
|
const subViews = [
|
|
{ id: 'conciliadas', label: 'Transações Conciliadas', icon: FileText, description: 'Navegação hierárquica por caixas' },
|
|
{ id: 'extrato-completo', label: 'Extrato Completo', icon: History, description: 'Todo o extrato com filtros' },
|
|
{ id: 'nao-categorizadas', label: 'Pendentes', icon: AlertCircle, description: 'Aguardando categorização' },
|
|
{ id: 'gerenciamento', label: 'Gerenciamento', icon: Settings, description: 'Caixas, Categorias, Regras' },
|
|
];
|
|
|
|
const renderSubView = () => {
|
|
switch (activeSubView) {
|
|
case 'conciliadas':
|
|
return <TransacoesConciliadasView state={state} actions={actions} />;
|
|
case 'extrato-completo':
|
|
return <ExtratoCompletoView state={state} actions={actions} />;
|
|
case 'nao-categorizadas':
|
|
return <TransacoesNaoCategorizadasView state={state} actions={actions} />;
|
|
case 'gerenciamento':
|
|
return <GerenciamentoView state={state} actions={actions} />;
|
|
default:
|
|
return <TransacoesConciliadasView state={state} actions={actions} />;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="animate-in fade-in duration-700 relative">
|
|
{/* Header Section */}
|
|
<div className="border-b border-slate-200 dark:border-slate-800 pb-4 sm:pb-6 mb-6 sm:mb-8">
|
|
{/* Linha 1: Título, Badge e Botão Activity Log */}
|
|
<div className="flex items-center justify-between gap-4 mb-4 sm:mb-6">
|
|
<h1 className="text-xl sm:text-2xl font-bold text-slate-900 dark:text-white tracking-tight flex items-center gap-2 sm:gap-3">
|
|
Conciliação
|
|
{/* <Badge className="bg-blue-500/10 text-blue-500 border-blue-500/20 text-[10px] hidden sm:inline-flex">PREMIUM v2</Badge> */}
|
|
</h1>
|
|
|
|
{/* <Button
|
|
size="sm"
|
|
variant="ghost"
|
|
className={cn(
|
|
"rounded-full w-9 h-9 p-0 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 shrink-0",
|
|
isBuzzOpen ? "text-blue-400 ring-2 ring-blue-500/20" : "text-slate-500"
|
|
)}
|
|
onClick={() => setIsBuzzOpen(!isBuzzOpen)}
|
|
>
|
|
<History className="w-4 h-4" />
|
|
</Button> */}
|
|
</div>
|
|
|
|
{/* Linha 2: Menu de Navegação */}
|
|
<div className="flex bg-slate-100/80 dark:bg-slate-900/80 p-1 rounded-xl border border-slate-200 dark:border-slate-800 shadow-inner flex-wrap gap-1 overflow-x-auto">
|
|
{subViews.map((view) => {
|
|
const Icon = view.icon;
|
|
return (
|
|
<Button
|
|
key={view.id}
|
|
variant="ghost"
|
|
onClick={() => actions?.setActiveSubView(view.id)}
|
|
className={cn(
|
|
"rounded-lg px-3 sm:px-4 h-8 sm:h-9 font-bold text-[9px] sm:text-[10px] uppercase tracking-widest transition-all duration-300 whitespace-nowrap shrink-0",
|
|
activeSubView === view.id
|
|
? "bg-white dark:bg-[#1e293b] text-slate-900 dark:text-white shadow-lg border border-slate-200 dark:border-slate-700"
|
|
: "text-slate-500 hover:text-slate-900 dark:hover:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-800"
|
|
)}
|
|
title={view.description}
|
|
>
|
|
<Icon className="w-3.5 h-3.5 sm:w-4 sm:h-4 sm:mr-2" />
|
|
<span className="hidden sm:inline">{view.label}</span>
|
|
<span className="sm:hidden">{view.label.split(' ')[0]}</span>
|
|
</Button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Content Area */}
|
|
{isLoading ? (
|
|
<div className="flex flex-col items-center justify-center min-h-[500px] gap-4">
|
|
<div className="w-16 h-16 border-4 border-blue-200 border-t-blue-600 rounded-full animate-spin shadow-[0_0_20px_rgba(59,130,246,0.2)]"></div>
|
|
<p className="text-[10px] font-bold text-slate-600 dark:text-slate-400 uppercase tracking-[0.3em] animate-pulse">Carregando Dados...</p>
|
|
</div>
|
|
) : (
|
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
|
|
<div className="lg:col-span-12">
|
|
{renderSubView()}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<ActivityLog
|
|
isOpen={isBuzzOpen}
|
|
onClose={() => setIsBuzzOpen(false)}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|