feat: tela de gerenciar equipe

This commit is contained in:
yagostn 2025-12-08 11:24:59 -03:00
parent b99807beb3
commit f89e1386f7
3 changed files with 374 additions and 83 deletions

View file

@ -204,7 +204,7 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
user.role === UserRole.SUPERADMIN) && ( user.role === UserRole.SUPERADMIN) && (
<button <button
onClick={() => { onClick={() => {
onNavigate("settings"); onNavigate("configuracoes");
setIsAccountDropdownOpen(false); setIsAccountDropdownOpen(false);
}} }}
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group" className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group"
@ -385,7 +385,7 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
user.role === UserRole.SUPERADMIN) && ( user.role === UserRole.SUPERADMIN) && (
<button <button
onClick={() => { onClick={() => {
onNavigate("settings"); onNavigate("configuracoes");
setIsAccountDropdownOpen(false); setIsAccountDropdownOpen(false);
}} }}
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group" className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group"

View file

@ -15,6 +15,9 @@ import {
Building2, Building2,
Calendar, Calendar,
MapPin, MapPin,
X,
UserCheck,
UserX,
} from "lucide-react"; } from "lucide-react";
import { useAuth } from "../contexts/AuthContext"; import { useAuth } from "../contexts/AuthContext";
import { useData } from "../contexts/DataContext"; import { useData } from "../contexts/DataContext";
@ -24,6 +27,125 @@ interface DashboardProps {
initialView?: "list" | "create"; initialView?: "list" | "create";
} }
interface Professional {
id: string;
name: string;
email: string;
avatar: string;
role: "Fotógrafo" | "Cinegrafista" | "Recepcionista";
availability: {
[date: string]: boolean;
};
}
// Mock de profissionais cadastrados
const MOCK_PHOTOGRAPHERS: Professional[] = [
{
id: "photographer-1",
name: "Carlos Silva",
email: "carlos@photum.com",
avatar: "https://i.pravatar.cc/150?u=carlos",
role: "Fotógrafo",
availability: {
"2025-12-05": true,
"2025-12-10": true,
"2025-12-15": false,
"2025-12-20": true,
},
},
{
id: "photographer-2",
name: "Ana Santos",
email: "ana@photum.com",
avatar: "https://i.pravatar.cc/150?u=ana",
role: "Fotógrafo",
availability: {
"2025-12-05": true,
"2025-12-10": false,
"2025-12-15": true,
"2025-12-20": true,
},
},
{
id: "photographer-3",
name: "João Oliveira",
email: "joao@photum.com",
avatar: "https://i.pravatar.cc/150?u=joao",
role: "Cinegrafista",
availability: {
"2025-12-05": false,
"2025-12-10": true,
"2025-12-15": true,
"2025-12-20": false,
},
},
{
id: "photographer-4",
name: "Maria Costa",
email: "maria@photum.com",
avatar: "https://i.pravatar.cc/150?u=maria",
role: "Fotógrafo",
availability: {
"2025-12-05": true,
"2025-12-10": true,
"2025-12-15": true,
"2025-12-20": true,
},
},
{
id: "photographer-5",
name: "Pedro Alves",
email: "pedro@photum.com",
avatar: "https://i.pravatar.cc/150?u=pedro",
role: "Cinegrafista",
availability: {
"2025-12-05": false,
"2025-12-10": false,
"2025-12-15": true,
"2025-12-20": true,
},
},
{
id: "receptionist-1",
name: "Julia Mendes",
email: "julia@photum.com",
avatar: "https://i.pravatar.cc/150?u=julia",
role: "Recepcionista",
availability: {
"2025-12-05": true,
"2025-12-10": true,
"2025-12-15": true,
"2025-12-20": false,
},
},
{
id: "receptionist-2",
name: "Rafael Souza",
email: "rafael@photum.com",
avatar: "https://i.pravatar.cc/150?u=rafael",
role: "Recepcionista",
availability: {
"2025-12-05": true,
"2025-12-10": true,
"2025-12-15": false,
"2025-12-20": true,
},
},
{
id: "videographer-1",
name: "Lucas Ferreira",
email: "lucas@photum.com",
avatar: "https://i.pravatar.cc/150?u=lucas",
role: "Cinegrafista",
availability: {
"2025-12-05": true,
"2025-12-10": false,
"2025-12-15": true,
"2025-12-20": true,
},
},
];
export const Dashboard: React.FC<DashboardProps> = ({ export const Dashboard: React.FC<DashboardProps> = ({
initialView = "list", initialView = "list",
}) => { }) => {
@ -50,6 +172,7 @@ export const Dashboard: React.FC<DashboardProps> = ({
timeRange: '', timeRange: '',
type: '', type: '',
}); });
const [isTeamModalOpen, setIsTeamModalOpen] = useState(false);
// Reset view when initialView prop changes // Reset view when initialView prop changes
useEffect(() => { useEffect(() => {
@ -157,17 +280,14 @@ export const Dashboard: React.FC<DashboardProps> = ({
}; };
const handleManageTeam = () => { const handleManageTeam = () => {
setIsTeamModalOpen(true);
};
const togglePhotographer = (photographerId: string) => {
if (!selectedEvent) return; if (!selectedEvent) return;
const newId = window.prompt( assignPhotographer(selectedEvent.id, photographerId);
"ID do Fotógrafo para adicionar (ex: photographer-1):", const updated = events.find((e) => e.id === selectedEvent.id);
"photographer-1" if (updated) setSelectedEvent(updated);
);
if (newId) {
assignPhotographer(selectedEvent.id, newId);
alert("Fotógrafo atribuído com sucesso!");
const updated = events.find((e) => e.id === selectedEvent.id);
if (updated) setSelectedEvent(updated);
}
}; };
// --- RENDERS PER ROLE --- // --- RENDERS PER ROLE ---
@ -588,18 +708,21 @@ export const Dashboard: React.FC<DashboardProps> = ({
{selectedEvent.photographerIds.length > 0 ? ( {selectedEvent.photographerIds.length > 0 ? (
<div className="space-y-2"> <div className="space-y-2">
{selectedEvent.photographerIds.map((id, idx) => ( {selectedEvent.photographerIds.map((id) => {
<div key={id} className="flex items-center gap-2 text-sm"> const photographer = MOCK_PHOTOGRAPHERS.find(p => p.id === id);
<div return (
className="w-8 h-8 rounded-full border-2 border-gray-200 bg-gray-300 flex-shrink-0" <div key={id} className="flex items-center gap-2 text-sm">
style={{ <div
backgroundImage: `url(https://i.pravatar.cc/100?u=${id})`, className="w-8 h-8 rounded-full border-2 border-gray-200 bg-gray-300 flex-shrink-0"
backgroundSize: "cover", style={{
}} backgroundImage: `url(${photographer?.avatar || `https://i.pravatar.cc/100?u=${id}`})`,
></div> backgroundSize: "cover",
<span className="text-gray-700">{id}</span> }}
</div> ></div>
))} <span className="text-gray-700">{photographer?.name || id}</span>
</div>
);
})}
</div> </div>
) : ( ) : (
<p className="text-sm text-gray-400 italic"> <p className="text-sm text-gray-400 italic">
@ -614,6 +737,178 @@ export const Dashboard: React.FC<DashboardProps> = ({
</div> </div>
</div> </div>
)} )}
{/* Modal de Gerenciamento de Equipe */}
{isTeamModalOpen && selectedEvent && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-2xl shadow-2xl max-w-6xl w-full max-h-[90vh] overflow-hidden flex flex-col">
{/* Header */}
<div className="bg-gradient-to-r from-[#492E61] to-[#5a3a7a] p-6 flex justify-between items-center">
<div>
<h2 className="text-2xl font-bold text-white mb-1">
Gerenciar Equipe
</h2>
<p className="text-white/80 text-sm">
{selectedEvent.name} - {new Date(selectedEvent.date + 'T00:00:00').toLocaleDateString('pt-BR')}
</p>
</div>
<button
onClick={() => setIsTeamModalOpen(false)}
className="text-white hover:bg-white/20 rounded-full p-2 transition-colors"
>
<X size={24} />
</button>
</div>
{/* Body */}
<div className="flex-1 overflow-auto p-6">
<div className="mb-4">
<p className="text-sm text-gray-600">
Profissionais disponíveis para a data <strong>{new Date(selectedEvent.date + 'T00:00:00').toLocaleDateString('pt-BR')}</strong>. Clique em "Adicionar" para atribuir ao evento.
</p>
</div>
{/* Tabela de Profissionais */}
<div className="overflow-x-auto">
<table className="w-full border-collapse">
<thead>
<tr className="bg-gray-50 border-b-2 border-gray-200">
<th className="text-left p-4 font-semibold text-gray-700">
Profissional
</th>
<th className="text-center p-4 font-semibold text-gray-700">
Função
</th>
<th className="text-center p-4 font-semibold text-gray-700">
E-mail
</th>
<th className="text-center p-4 font-semibold text-gray-700">
Status
</th>
<th className="text-center p-4 font-semibold text-gray-700">
Ação
</th>
</tr>
</thead>
<tbody>
{MOCK_PHOTOGRAPHERS
.filter((photographer) => {
const isAssigned = selectedEvent.photographerIds.includes(photographer.id);
const isAvailable = photographer.availability[selectedEvent.date] ?? false;
return isAvailable || isAssigned;
})
.map((photographer) => {
const isAssigned = selectedEvent.photographerIds.includes(photographer.id);
const isAvailable = photographer.availability[selectedEvent.date] ?? false;
return (
<tr
key={photographer.id}
className="border-b border-gray-100 hover:bg-gray-50 transition-colors"
>
{/* Profissional */}
<td className="p-4">
<div className="flex items-center gap-3">
<div
className="w-10 h-10 rounded-full border-2 border-gray-200 bg-gray-300 flex-shrink-0"
style={{
backgroundImage: `url(${photographer.avatar})`,
backgroundSize: "cover",
}}
/>
<div>
<p className="font-semibold text-gray-900">
{photographer.name}
</p>
<p className="text-xs text-gray-500">
ID: {photographer.id}
</p>
</div>
</div>
</td>
{/* Função */}
<td className="p-4 text-center">
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-purple-100 text-purple-800">
{photographer.role}
</span>
</td>
{/* E-mail */}
<td className="p-4 text-center text-sm text-gray-600">
{photographer.email}
</td>
{/* Status */}
<td className="p-4 text-center">
{isAssigned ? (
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-brand-gold/20 text-brand-black rounded-full text-xs font-medium">
<CheckCircle size={14} />
Atribuído
</span>
) : (
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-green-100 text-green-800 rounded-full text-xs font-medium">
<UserCheck size={14} />
Disponível
</span>
)}
</td>
{/* Ação */}
<td className="p-4 text-center">
<button
onClick={() => togglePhotographer(photographer.id)}
disabled={!isAvailable && !isAssigned}
className={`px-4 py-2 rounded-lg font-medium text-sm transition-colors ${
isAssigned
? "bg-red-100 text-red-700 hover:bg-red-200"
: isAvailable
? "bg-brand-gold text-white hover:bg-[#a5bd2e]"
: "bg-gray-100 text-gray-400 cursor-not-allowed"
}`}
>
{isAssigned ? "Remover" : "Adicionar"}
</button>
</td>
</tr>
);
})}
{MOCK_PHOTOGRAPHERS.filter((p) => {
const isAssigned = selectedEvent.photographerIds.includes(p.id);
const isAvailable = p.availability[selectedEvent.date] ?? false;
return isAvailable || isAssigned;
}).length === 0 && (
<tr>
<td colSpan={5} className="p-8 text-center">
<div className="flex flex-col items-center gap-3">
<UserX size={48} className="text-gray-300" />
<p className="text-gray-500 font-medium">
Nenhum profissional disponível para esta data
</p>
<p className="text-sm text-gray-400">
Tente selecionar outra data ou entre em contato com a equipe
</p>
</div>
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
{/* Footer */}
<div className="border-t border-gray-200 p-6 bg-gray-50 flex justify-end gap-3">
<Button
variant="outline"
onClick={() => setIsTeamModalOpen(false)}
>
Fechar
</Button>
</div>
</div>
</div>
)}
</div> </div>
</div> </div>
); );

View file

@ -192,41 +192,41 @@ export const FinancePage: React.FC = () => {
{/* Stats Cards */} {/* Stats Cards */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-6 sm:mb-8"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-6 sm:mb-8">
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6"> <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-4 sm:p-6">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<p className="text-sm text-gray-600">Receitas</p> <p className="text-xs sm:text-sm text-gray-600">Receitas</p>
<TrendingUp className="text-green-600" size={24} /> <TrendingUp className="text-green-600" size={20} />
</div> </div>
<p className="text-3xl font-bold text-green-600">{formatCurrency(totalIncome)}</p> <p className="text-2xl sm:text-3xl font-bold text-green-600">{formatCurrency(totalIncome)}</p>
<p className="text-xs text-gray-500 mt-1">Pagamentos recebidos</p> <p className="text-xs text-gray-500 mt-1">Pagamentos recebidos</p>
</div> </div>
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6"> <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-4 sm:p-6">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<p className="text-sm text-gray-600">Despesas</p> <p className="text-xs sm:text-sm text-gray-600">Despesas</p>
<TrendingDown className="text-red-600" size={24} /> <TrendingDown className="text-red-600" size={20} />
</div> </div>
<p className="text-3xl font-bold text-red-600">{formatCurrency(totalExpense)}</p> <p className="text-2xl sm:text-3xl font-bold text-red-600">{formatCurrency(totalExpense)}</p>
<p className="text-xs text-gray-500 mt-1">Gastos do período</p> <p className="text-xs text-gray-500 mt-1">Gastos do período</p>
</div> </div>
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6"> <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-4 sm:p-6">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<p className="text-sm text-gray-600">Saldo</p> <p className="text-xs sm:text-sm text-gray-600">Saldo</p>
<DollarSign className="text-brand-gold" size={24} /> <DollarSign className="text-brand-gold" size={20} />
</div> </div>
<p className={`text-3xl font-bold ${balance >= 0 ? 'text-brand-gold' : 'text-red-600'}`}> <p className={`text-2xl sm:text-3xl font-bold ${balance >= 0 ? 'text-brand-gold' : 'text-red-600'}`}>
{formatCurrency(balance)} {formatCurrency(balance)}
</p> </p>
<p className="text-xs text-gray-500 mt-1">Receitas - Despesas</p> <p className="text-xs text-gray-500 mt-1">Receitas - Despesas</p>
</div> </div>
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6"> <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-4 sm:p-6">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<p className="text-sm text-gray-600">A Receber</p> <p className="text-xs sm:text-sm text-gray-600">A Receber</p>
<Clock className="text-yellow-600" size={24} /> <Clock className="text-yellow-600" size={20} />
</div> </div>
<p className="text-3xl font-bold text-yellow-600">{formatCurrency(pendingIncome)}</p> <p className="text-2xl sm:text-3xl font-bold text-yellow-600">{formatCurrency(pendingIncome)}</p>
<p className="text-xs text-gray-500 mt-1">Pagamentos pendentes</p> <p className="text-xs text-gray-500 mt-1">Pagamentos pendentes</p>
</div> </div>
</div> </div>
@ -237,7 +237,7 @@ export const FinancePage: React.FC = () => {
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
<button <button
onClick={() => setFilterType('all')} onClick={() => setFilterType('all')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterType === 'all' className={`px-3 sm:px-4 py-1.5 sm:py-2 rounded-md text-xs sm:text-sm font-medium transition-colors ${filterType === 'all'
? 'bg-brand-gold text-white' ? 'bg-brand-gold text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`} }`}
@ -246,7 +246,7 @@ export const FinancePage: React.FC = () => {
</button> </button>
<button <button
onClick={() => setFilterType('income')} onClick={() => setFilterType('income')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterType === 'income' className={`px-3 sm:px-4 py-1.5 sm:py-2 rounded-md text-xs sm:text-sm font-medium transition-colors ${filterType === 'income'
? 'bg-green-600 text-white' ? 'bg-green-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`} }`}
@ -255,7 +255,7 @@ export const FinancePage: React.FC = () => {
</button> </button>
<button <button
onClick={() => setFilterType('expense')} onClick={() => setFilterType('expense')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterType === 'expense' className={`px-3 sm:px-4 py-1.5 sm:py-2 rounded-md text-xs sm:text-sm font-medium transition-colors ${filterType === 'expense'
? 'bg-red-600 text-white' ? 'bg-red-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`} }`}
@ -266,7 +266,7 @@ export const FinancePage: React.FC = () => {
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
<button <button
onClick={() => setFilterStatus('all')} onClick={() => setFilterStatus('all')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterStatus === 'all' className={`px-3 sm:px-4 py-1.5 sm:py-2 rounded-md text-xs sm:text-sm font-medium transition-colors ${filterStatus === 'all'
? 'bg-brand-black text-white' ? 'bg-brand-black text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`} }`}
@ -275,7 +275,7 @@ export const FinancePage: React.FC = () => {
</button> </button>
<button <button
onClick={() => setFilterStatus('paid')} onClick={() => setFilterStatus('paid')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterStatus === 'paid' className={`px-3 sm:px-4 py-1.5 sm:py-2 rounded-md text-xs sm:text-sm font-medium transition-colors ${filterStatus === 'paid'
? 'bg-green-600 text-white' ? 'bg-green-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`} }`}
@ -284,7 +284,7 @@ export const FinancePage: React.FC = () => {
</button> </button>
<button <button
onClick={() => setFilterStatus('pending')} onClick={() => setFilterStatus('pending')}
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterStatus === 'pending' className={`px-3 sm:px-4 py-1.5 sm:py-2 rounded-md text-xs sm:text-sm font-medium transition-colors ${filterStatus === 'pending'
? 'bg-yellow-600 text-white' ? 'bg-yellow-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`} }`}
@ -297,13 +297,13 @@ export const FinancePage: React.FC = () => {
{/* Transactions List */} {/* Transactions List */}
<div className="bg-white rounded-lg shadow-sm border border-gray-200"> <div className="bg-white rounded-lg shadow-sm border border-gray-200">
<div className="p-6 border-b border-gray-200"> <div className="p-4 sm:p-6 border-b border-gray-200">
<h2 className="text-xl font-semibold">Transações</h2> <h2 className="text-lg sm:text-xl font-semibold">Transações</h2>
</div> </div>
<div className="divide-y divide-gray-200"> <div className="divide-y divide-gray-200">
{filteredTransactions.length === 0 ? ( {filteredTransactions.length === 0 ? (
<div className="p-12 text-center text-gray-500"> <div className="p-8 sm:p-12 text-center text-gray-500">
<CreditCard size={48} className="mx-auto mb-4 text-gray-300" /> <CreditCard size={48} className="mx-auto mb-4 text-gray-300" />
<p>Nenhuma transação encontrada</p> <p>Nenhuma transação encontrada</p>
</div> </div>
@ -311,48 +311,44 @@ export const FinancePage: React.FC = () => {
filteredTransactions.map((transaction) => ( filteredTransactions.map((transaction) => (
<div <div
key={transaction.id} key={transaction.id}
className="p-6 hover:bg-gray-50 transition-colors" className="p-4 sm:p-6 hover:bg-gray-50 transition-colors"
> >
<div className="flex items-center justify-between"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div className="flex-1"> <div className="flex items-start gap-3 flex-1">
<div className="flex items-center gap-3 mb-2"> <div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${transaction.type === 'income' ? 'bg-green-100' : 'bg-red-100'
<div className={`w-10 h-10 rounded-full flex items-center justify-center ${transaction.type === 'income' ? 'bg-green-100' : 'bg-red-100' }`}>
}`}> {transaction.type === 'income' ? (
{transaction.type === 'income' ? ( <TrendingUp size={20} className="text-green-600" />
<TrendingUp size={20} className="text-green-600" /> ) : (
) : ( <TrendingDown size={20} className="text-red-600" />
<TrendingDown size={20} className="text-red-600" /> )}
</div>
<div className="flex-1 min-w-0">
<h3 className="font-semibold text-sm sm:text-base text-brand-black">
{transaction.description}
</h3>
<div className="flex flex-wrap items-center gap-1.5 mt-1">
<span className="text-xs text-gray-500">{transaction.category}</span>
{transaction.client && (
<>
<span className="text-xs text-gray-300"></span>
<span className="text-xs text-gray-500 truncate">{transaction.client}</span>
</>
)} )}
</div> </div>
<div>
<h3 className="font-semibold text-brand-black">
{transaction.description}
</h3>
<div className="flex items-center gap-2 mt-1">
<span className="text-xs text-gray-500">{transaction.category}</span>
{transaction.client && (
<>
<span className="text-xs text-gray-300"></span>
<span className="text-xs text-gray-500">{transaction.client}</span>
</>
)}
</div>
</div>
</div>
</div>
<div className="flex items-center gap-4">
<div className="text-right">
<p className={`text-lg font-bold ${transaction.type === 'income' ? 'text-green-600' : 'text-red-600'
}`}>
{transaction.type === 'income' ? '+' : '-'} {formatCurrency(transaction.amount)}
</p>
<div className="flex items-center gap-1 text-xs text-gray-500 mt-1"> <div className="flex items-center gap-1 text-xs text-gray-500 mt-1">
<Calendar size={12} /> <Calendar size={12} />
{formatDate(transaction.date)} {formatDate(transaction.date)}
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> </div>
<div className="flex items-center justify-between sm:justify-end gap-3 sm:gap-4 ml-13 sm:ml-0">
<p className={`text-lg sm:text-xl font-bold ${transaction.type === 'income' ? 'text-green-600' : 'text-red-600'
}`}>
{transaction.type === 'income' ? '+' : '-'} {formatCurrency(transaction.amount)}
</p>
<div className="flex items-center gap-1.5">
{getStatusIcon(transaction.status)} {getStatusIcon(transaction.status)}
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getStatusColor(transaction.status)}`}> <span className={`px-2 py-1 rounded-full text-xs font-medium ${getStatusColor(transaction.status)}`}>
{getStatusLabel(transaction.status)} {getStatusLabel(transaction.status)}