Files
course-plat/src/app/(protected)/admin/dashboard/payments/components/ObligationDetails.jsx
T
2026-08-31 14:10:20 -03:00

165 lines
6.5 KiB
React

"use client";
import { useState } from "react";
import { format } from "date-fns";
import { ptBR } from "date-fns/locale";
import Label from "@/app/(protected)/components/shared/Label";
import { getPaymentsByObligationAction } from "@/app/lib/payments/actions";
export default function ObligationDetails({ obligations }) {
const [expandedObligation, setExpandedObligation] = useState(null);
const [obligationPayments, setObligationPayments] = useState({});
const [loading, setLoading] = useState(false);
// Group obligations by their reference (description + dueDate)
const groupedObligations = obligations.reduce((acc, obligation) => {
const key = `${obligation.description || "Pagamento"}_${obligation.dueDate || obligation.createdAt}`;
if (!acc[key]) {
acc[key] = {
...obligation,
users: [],
};
}
acc[key].users.push(obligation);
return acc;
}, {});
const groupedList = Object.values(groupedObligations);
const fetchPaymentsForObligation = async (obligation) => {
setLoading(true);
try {
const result = await getPaymentsByObligationAction(obligation._id);
if (result.success) {
setObligationPayments(prev => ({
...prev,
[obligation._id]: result.data || [],
}));
}
} catch (error) {
console.error("Error fetching payments:", error);
} finally {
setLoading(false);
}
};
const handleToggleExpand = (obligation) => {
if (expandedObligation === obligation._id) {
setExpandedObligation(null);
} else {
setExpandedObligation(obligation._id);
if (!obligationPayments[obligation._id]) {
fetchPaymentsForObligation(obligation);
}
}
};
const getStatusBadge = (userObligation) => {
const payments = obligationPayments[userObligation._id] || [];
const hasVerified = payments.some(p => p.status === "verified");
const hasPending = payments.some(p => p.status === "pending_verification");
if (hasVerified) {
return <Label color="emerald" size="sm"> Pago</Label>;
}
if (hasPending) {
return <Label color="blue" size="sm">Aguardando Verificação</Label>;
}
return <Label color="amber" size="sm">Aguardando Pagamento</Label>;
};
if (obligations.length === 0) {
return (
<div className="bg-white dark:bg-neutral-800 rounded-lg shadow p-6 text-center text-gray-500 dark:text-gray-200 label-dark">
Nenhuma obrigação de pagamento criada ainda.
</div>
);
}
return (
<div className="space-y-4">
{groupedList.map((group) => (
<div
key={group._id}
className="bg-white dark:bg-neutral-800 rounded-lg shadow overflow-hidden"
>
{/* Group Header */}
<div
className="p-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-neutral-700/50 transition-colors"
onClick={() => handleToggleExpand(group)}
>
<div className="flex justify-between items-center">
<div>
<h3 className="font-semibold text-gray-900 dark:text-neutral-100">
{group.description || "Pagamento"}
</h3>
<p className="text-sm text-gray-500 dark:text-gray-200 label-dark">
Vencimento: {format(new Date(group.dueDate || group.createdAt), "dd/MM/yyyy", { locale: ptBR })}
</p>
</div>
<div className="flex items-center gap-4">
<div className="text-right">
<p className="text-sm text-gray-500 dark:text-gray-200 label-dark">
{group.users.length} {group.users.length === 1 ? "aluno" : "alunos"}
</p>
<p className="text-lg font-bold text-gray-900 dark:text-neutral-100">
R$ {group.amount?.toFixed(2)}
</p>
</div>
<span className="text-gray-400 dark:text-neutral-500">
{expandedObligation === group._id ? "▼" : "▶"}
</span>
</div>
</div>
</div>
{/* Expanded Details */}
{expandedObligation === group._id && (
<div className="border-t border-gray-200 dark:border-neutral-700">
<table className="min-w-full divide-y divide-gray-200 dark:divide-neutral-700">
<thead className="bg-gray-50 dark:bg-neutral-700">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-200 label-dark uppercase tracking-wider">
Aluno
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-200 label-dark uppercase tracking-wider">
Email
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-200 label-dark uppercase tracking-wider">
Valor
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-200 label-dark uppercase tracking-wider">
Status
</th>
</tr>
</thead>
<tbody className="bg-white dark:bg-neutral-800 divide-y divide-gray-200 dark:divide-neutral-700">
{group.users.map((userObligation) => (
<tr
key={userObligation._id}
className="hover:bg-gray-50 dark:hover:bg-neutral-700/50"
>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-neutral-100">
{userObligation.userId?.fullName || "N/A"}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-200 label-dark">
{userObligation.userId?.email || "N/A"}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-neutral-100 font-medium">
R$ {userObligation.amount?.toFixed(2) || "0.00"}
</td>
<td className="px-6 py-4 whitespace-nowrap">
{getStatusBadge(userObligation)}
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
))}
</div>
);
}