Fix: Restore user identification and improve chart
Restore the user identification section in the header. Improve the category chart by removing the value from the center and improving the tooltip display.
This commit is contained in:
parent
bfad740ccb
commit
36b64f7e5c
@ -11,7 +11,6 @@ interface CategoryChartProps {
|
|||||||
|
|
||||||
const CategoryChart: React.FC<CategoryChartProps> = ({ categories, isLoading = false }) => {
|
const CategoryChart: React.FC<CategoryChartProps> = ({ categories, isLoading = false }) => {
|
||||||
const validCategories = categories.filter(cat => cat.valor > 0);
|
const validCategories = categories.filter(cat => cat.valor > 0);
|
||||||
const totalValue = validCategories.reduce((sum, cat) => sum + cat.valor, 0);
|
|
||||||
|
|
||||||
const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }: any) => {
|
const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }: any) => {
|
||||||
if (percent < 0.05) return null;
|
if (percent < 0.05) return null;
|
||||||
@ -60,10 +59,10 @@ const CategoryChart: React.FC<CategoryChartProps> = ({ categories, isLoading = f
|
|||||||
const renderCustomTooltip = ({ active, payload }: any) => {
|
const renderCustomTooltip = ({ active, payload }: any) => {
|
||||||
if (active && payload && payload.length) {
|
if (active && payload && payload.length) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-zinc-900 border border-gray-200 dark:border-zinc-700 p-2 rounded-xl shadow-lg transition-all duration-300">
|
<div className="bg-white dark:bg-zinc-900 border border-gray-200 dark:border-zinc-700 p-3 rounded-xl shadow-lg transition-all duration-300">
|
||||||
<p className="font-semibold text-sm text-zinc-800 dark:text-white">{payload[0].name}</p>
|
<p className="font-semibold text-sm text-zinc-800 dark:text-white mb-1">{payload[0].name}</p>
|
||||||
<p className="font-bold">{formatCurrency(payload[0].value)}</p>
|
<p className="font-bold text-base">{formatCurrency(payload[0].value)}</p>
|
||||||
<p className="text-xs">{`${(payload[0].payload.percentage * 100).toFixed(1)}%`}</p>
|
<p className="text-xs text-gray-600 dark:text-gray-400">{`${(payload[0].payload.percentage * 100).toFixed(1)}%`}</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -88,17 +87,17 @@ const CategoryChart: React.FC<CategoryChartProps> = ({ categories, isLoading = f
|
|||||||
<span className="text-xs mt-2">Verifique se existem transações do tipo 'despesa' cadastradas</span>
|
<span className="text-xs mt-2">Verifique se existem transações do tipo 'despesa' cadastradas</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-[320px] relative">
|
<div className="h-[300px] relative">
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
<PieChart>
|
<PieChart>
|
||||||
<Pie
|
<Pie
|
||||||
data={validCategories}
|
data={validCategories}
|
||||||
cx="50%"
|
cx="50%"
|
||||||
cy="46%"
|
cy="45%"
|
||||||
labelLine={false}
|
labelLine={false}
|
||||||
label={renderCustomizedLabel}
|
label={renderCustomizedLabel}
|
||||||
outerRadius={105}
|
outerRadius={90}
|
||||||
innerRadius={65}
|
innerRadius={40}
|
||||||
fill="#8884d8"
|
fill="#8884d8"
|
||||||
dataKey="valor"
|
dataKey="valor"
|
||||||
nameKey="categoria"
|
nameKey="categoria"
|
||||||
@ -120,13 +119,6 @@ const CategoryChart: React.FC<CategoryChartProps> = ({ categories, isLoading = f
|
|||||||
<Legend content={renderCustomLegend} layout="horizontal" verticalAlign="bottom" />
|
<Legend content={renderCustomLegend} layout="horizontal" verticalAlign="bottom" />
|
||||||
</PieChart>
|
</PieChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
{/* Valor total no centro */}
|
|
||||||
<div
|
|
||||||
className="absolute top-[46%] left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-center pointer-events-none"
|
|
||||||
style={{ width: '120px' }}
|
|
||||||
>
|
|
||||||
<div className="font-bold text-lg text-zinc-800 dark:text-white">{formatCurrency(totalValue)}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@ -1,7 +1,17 @@
|
|||||||
|
|
||||||
import { Menu } from 'lucide-react';
|
import { Menu, User, LogOut } from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useIsMobile } from '@/hooks/use-mobile';
|
import { useIsMobile } from '@/hooks/use-mobile';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
|
import { useToast } from '@/hooks/use-toast';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
onMenuToggle: () => void;
|
onMenuToggle: () => void;
|
||||||
@ -9,6 +19,45 @@ interface HeaderProps {
|
|||||||
|
|
||||||
export default function Header({ onMenuToggle }: HeaderProps) {
|
export default function Header({ onMenuToggle }: HeaderProps) {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const { toast } = useToast();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [userEmail, setUserEmail] = useState<string>('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Buscar dados do usuário logado
|
||||||
|
const getUserData = async () => {
|
||||||
|
const { data: { user } } = await supabase.auth.getUser();
|
||||||
|
if (user?.email) {
|
||||||
|
setUserEmail(user.email);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getUserData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleLogout = async () => {
|
||||||
|
try {
|
||||||
|
const { error } = await supabase.auth.signOut();
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
// Limpar localStorage
|
||||||
|
localStorage.removeItem('userEmail');
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: "Logout realizado",
|
||||||
|
description: "Você foi desconectado com sucesso"
|
||||||
|
});
|
||||||
|
|
||||||
|
navigate('/auth');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro no logout:', error);
|
||||||
|
toast({
|
||||||
|
title: "Erro no logout",
|
||||||
|
description: "Ocorreu um erro ao sair da conta",
|
||||||
|
variant: "destructive"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-14 items-center gap-4 border-b px-4 lg:h-[60px] lg:px-6">
|
<div className="flex h-14 items-center gap-4 border-b px-4 lg:h-[60px] lg:px-6">
|
||||||
@ -26,6 +75,29 @@ export default function Header({ onMenuToggle }: HeaderProps) {
|
|||||||
<div className="w-full flex-1">
|
<div className="w-full flex-1">
|
||||||
<h1 className="text-lg font-semibold md:text-2xl">Finance Home</h1>
|
<h1 className="text-lg font-semibold md:text-2xl">Finance Home</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* User Menu */}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="ghost" className="flex items-center gap-2 hover:bg-gray-100">
|
||||||
|
<User className="h-4 w-4" />
|
||||||
|
<span className="hidden md:inline-block text-sm">
|
||||||
|
{userEmail || 'Usuário'}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end" className="w-56">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={handleLogout}
|
||||||
|
className="flex items-center gap-2 text-red-600 hover:text-red-700 hover:bg-red-50"
|
||||||
|
>
|
||||||
|
<LogOut className="h-4 w-4" />
|
||||||
|
Sair
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user