feat(contribuyentes): mostrar contador de RFCs disponibles del plan

- Agrega contador 'X de Y RFCs' debajo del título de la página
- Usa DESPACHO_PLANS desde @horux/shared para obtener maxRfcs del plan actual
- Durante trial muestra 'X de 5 RFCs'
- Planes ilimitados muestran solo 'X RFCs'
This commit is contained in:
Horux Dev
2026-05-25 16:20:37 +00:00
parent 4c7ab4fd35
commit 1d828adc27

View File

@@ -9,6 +9,7 @@ import { useAuthStore } from '@/stores/auth-store';
import { apiClient } from '@/lib/api/client'; import { apiClient } from '@/lib/api/client';
import { Plus, Pencil, Trash2, Building2, Sparkles } from 'lucide-react'; import { Plus, Pencil, Trash2, Building2, Sparkles } from 'lucide-react';
import { AddonsDialog } from './addons-dialog'; import { AddonsDialog } from './addons-dialog';
import { DESPACHO_PLANS } from '@horux/shared';
const TRIAL_LIMIT_TOOLTIP = 'Límite de contribuyentes para la prueba gratuita, para continuar agregando contribuyentes, selecciona un plan.'; const TRIAL_LIMIT_TOOLTIP = 'Límite de contribuyentes para la prueba gratuita, para continuar agregando contribuyentes, selecciona un plan.';
@@ -30,11 +31,21 @@ export default function ContribuyentesPage() {
// deshabilita el botón con tooltip explicativo. // deshabilita el botón con tooltip explicativo.
const { data: planInfo } = useQuery({ const { data: planInfo } = useQuery({
queryKey: ['my-plan-info'], queryKey: ['my-plan-info'],
queryFn: () => apiClient.get<{ isTrialActive: boolean }>('/despachos/me/plan').then(r => r.data), queryFn: () => apiClient.get<{ plan: string; isTrialActive: boolean }>('/despachos/me/plan').then(r => r.data),
}); });
const activeCount = (contribuyentes ?? []).filter((c: any) => c.active !== false).length; const activeCount = (contribuyentes ?? []).filter((c: any) => c.active !== false).length;
const trialAtLimit = (planInfo?.isTrialActive ?? false) && activeCount >= 5; const trialAtLimit = (planInfo?.isTrialActive ?? false) && activeCount >= 5;
// Contador de RFCs disponibles en el plan
const planKey = planInfo?.plan as keyof typeof DESPACHO_PLANS | undefined;
const planMaxRfcs = planKey ? DESPACHO_PLANS[planKey]?.maxRfcs ?? undefined : undefined;
const rfcCounterText = (() => {
if (planInfo?.isTrialActive) return `${activeCount} de 5 RFCs`;
if (planMaxRfcs != null && planMaxRfcs < 0) return `${activeCount} RFCs`;
if (planMaxRfcs !== undefined) return `${activeCount} de ${planMaxRfcs} RFCs`;
return `${activeCount} RFCs`;
})();
const resetForm = () => { setForm({ rfc: '', razonSocial: '' }); setAssignSelf(true); setShowDialog(false); setEditingId(null); }; const resetForm = () => { setForm({ rfc: '', razonSocial: '' }); setAssignSelf(true); setShowDialog(false); setEditingId(null); };
const handleSave = async () => { const handleSave = async () => {
@@ -80,7 +91,10 @@ export default function ContribuyentesPage() {
return ( return (
<div className="p-6 space-y-6 max-w-7xl mx-auto"> <div className="p-6 space-y-6 max-w-7xl mx-auto">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div><h1 className="text-2xl font-bold">Contribuyentes</h1><p className="text-sm text-muted-foreground">RFCs que gestiona tu despacho</p></div> <div>
<h1 className="text-2xl font-bold">Contribuyentes</h1>
<p className="text-sm text-muted-foreground">RFCs que gestiona tu despacho · {rfcCounterText}</p>
</div>
<Button <Button
onClick={() => { resetForm(); setShowDialog(true); }} onClick={() => { resetForm(); setShowDialog(true); }}
disabled={trialAtLimit} disabled={trialAtLimit}