108 lines
5.4 KiB
TypeScript
108 lines
5.4 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import api from '../../services/api';
|
|
|
|
interface Favorito {
|
|
id: string;
|
|
user_id: string;
|
|
property_id?: string;
|
|
created_at: string;
|
|
user_name?: string;
|
|
property_title?: string;
|
|
}
|
|
|
|
export default function AdminFavoritosPage() {
|
|
const [favoritos, setFavoritos] = useState<Favorito[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [removing, setRemoving] = useState<Favorito | null>(null);
|
|
const [actionLoading, setActionLoading] = useState(false);
|
|
|
|
function fetchFavoritos() {
|
|
setLoading(true);
|
|
api.get('/admin/favoritos')
|
|
.then(res => setFavoritos(res.data))
|
|
.catch(() => setError('Erro ao carregar favoritos'))
|
|
.finally(() => setLoading(false));
|
|
}
|
|
|
|
useEffect(() => { fetchFavoritos(); }, []);
|
|
|
|
function handleRemove() {
|
|
if (!removing) return;
|
|
setActionLoading(true);
|
|
api.delete(`/admin/favoritos/${removing.id}`)
|
|
.then(() => { setRemoving(null); fetchFavoritos(); })
|
|
.catch(() => setError('Erro ao remover favorito'))
|
|
.finally(() => setActionLoading(false));
|
|
}
|
|
|
|
return (
|
|
<div className="p-6 md:p-8">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<h2 className="text-xl font-bold text-textPrimary">Favoritos</h2>
|
|
</div>
|
|
{loading && <div className="text-textSecondary text-sm">Carregando...</div>}
|
|
{error && <div className="text-red-400 text-sm">{error}</div>}
|
|
<div className="overflow-x-auto rounded-xl border border-borderPrimary">
|
|
<table className="min-w-full bg-panel text-sm">
|
|
<thead>
|
|
<tr className="text-left text-textSecondary border-b border-borderSubtle">
|
|
<th className="py-3 px-4 font-medium">Cliente</th>
|
|
<th className="py-3 px-4 font-medium hidden sm:table-cell">Imóvel</th>
|
|
<th className="py-3 px-4 font-medium hidden md:table-cell">Adicionado em</th>
|
|
<th className="py-3 px-4 font-medium">Ações</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{favoritos.length === 0 && !loading && (
|
|
<tr>
|
|
<td colSpan={4} className="py-8 text-center text-textTertiary">
|
|
Nenhum favorito encontrado.
|
|
</td>
|
|
</tr>
|
|
)}
|
|
{favoritos.map(f => (
|
|
<tr key={f.id} className="border-t border-borderSubtle text-textPrimary hover:bg-surface/50 transition-colors">
|
|
<td className="py-3 px-4">{f.user_name || f.user_id || '—'}</td>
|
|
<td className="py-3 px-4 hidden sm:table-cell text-textSecondary">{f.property_title || '—'}</td>
|
|
<td className="py-3 px-4 hidden md:table-cell text-textSecondary">{f.created_at.slice(0, 10)}</td>
|
|
<td className="py-3 px-4">
|
|
<button
|
|
className="text-red-400 hover:text-red-300 text-xs font-medium transition-colors"
|
|
onClick={() => setRemoving(f)}
|
|
>Remover</button>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{/* Modal remoção */}
|
|
{removing && (
|
|
<div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4">
|
|
<div className="bg-panel border border-borderPrimary rounded-xl shadow-lg p-6 w-full max-w-md">
|
|
<h3 className="text-textPrimary font-semibold mb-2">Remover favorito</h3>
|
|
<p className="text-textSecondary text-sm mb-4">
|
|
Tem certeza que deseja remover o favorito de{' '}
|
|
<span className="text-textPrimary font-medium">{removing.user_name || removing.user_id}</span>
|
|
{' '}para o imóvel{' '}
|
|
<span className="text-textPrimary font-medium">{removing.property_title || '—'}</span>?
|
|
</p>
|
|
<div className="flex gap-2 justify-end">
|
|
<button
|
|
className="px-4 py-2 rounded border border-borderPrimary text-textSecondary hover:text-textPrimary hover:border-borderSecondary text-sm transition-colors"
|
|
onClick={() => setRemoving(null)}
|
|
>Cancelar</button>
|
|
<button
|
|
className="px-4 py-2 rounded bg-red-600 hover:bg-red-500 text-white text-sm font-medium transition-colors disabled:opacity-50"
|
|
onClick={handleRemove}
|
|
disabled={actionLoading}
|
|
>Remover</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|