Initial commit - Horux Despachos NL
This commit is contained in:
161
apps/web/lib/hooks/use-subscription.ts
Normal file
161
apps/web/lib/hooks/use-subscription.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
'use client';
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import * as subscriptionApi from '../api/subscription';
|
||||
import { apiClient } from '../api/client';
|
||||
|
||||
/**
|
||||
* Adaptador del catálogo despacho (`/planes/despacho`) al shape legacy que espera
|
||||
* `/configuracion/suscripcion`: `{ plan, frequency, amount }[]`. El catálogo
|
||||
* despacho tiene precios separados `monthly` / `firstYear` / `renewal` que aquí
|
||||
* proyectamos como dos filas (`monthly` y `annual`) por plan, usando `firstYear`
|
||||
* como precio anual cuando existe (precio "vitrina" de venta nueva).
|
||||
*
|
||||
* Mantiene la API pública del page sin migración invasiva — cuando se rehaga la
|
||||
* página para soportar dualidad de precios firstYear/renewal nativamente, este
|
||||
* adapter se puede borrar.
|
||||
*/
|
||||
interface DespachoPlanLimits {
|
||||
plan: string;
|
||||
monthly: number | null;
|
||||
firstYear: number | null;
|
||||
renewal: number | null;
|
||||
permiteMonthly: boolean;
|
||||
}
|
||||
|
||||
interface PlanPriceRow {
|
||||
plan: string;
|
||||
frequency: 'monthly' | 'annual';
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export function usePlans() {
|
||||
return useQuery<PlanPriceRow[]>({
|
||||
queryKey: ['despacho-catalogo-as-plans'],
|
||||
queryFn: async () => {
|
||||
const res = await apiClient.get<{ data: DespachoPlanLimits[] }>('/planes/despacho');
|
||||
const rows: PlanPriceRow[] = [];
|
||||
for (const p of res.data.data) {
|
||||
if (p.permiteMonthly && p.monthly != null) {
|
||||
rows.push({ plan: p.plan, frequency: 'monthly', amount: p.monthly });
|
||||
}
|
||||
const annual = p.firstYear ?? p.renewal;
|
||||
if (annual != null) {
|
||||
rows.push({ plan: p.plan, frequency: 'annual', amount: annual });
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useSubscription(tenantId: string | undefined) {
|
||||
return useQuery({
|
||||
queryKey: ['subscription', tenantId],
|
||||
queryFn: () => subscriptionApi.getSubscription(tenantId!),
|
||||
enabled: !!tenantId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
export function usePaymentHistory(tenantId: string | undefined) {
|
||||
return useQuery({
|
||||
queryKey: ['payments', tenantId],
|
||||
queryFn: () => subscriptionApi.getPaymentHistory(tenantId!),
|
||||
enabled: !!tenantId,
|
||||
staleTime: 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useGeneratePaymentLink() {
|
||||
return useMutation({
|
||||
mutationFn: (tenantId: string) => subscriptionApi.generatePaymentLink(tenantId),
|
||||
});
|
||||
}
|
||||
|
||||
export function useMarkAsPaid() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ tenantId, amount }: { tenantId: string; amount: number }) =>
|
||||
subscriptionApi.markAsPaid(tenantId, amount),
|
||||
onSuccess: (_, { tenantId }) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription', tenantId] });
|
||||
queryClient.invalidateQueries({ queryKey: ['payments', tenantId] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Self-serve hooks (actúan sobre el tenant del usuario autenticado)
|
||||
// ============================================================================
|
||||
|
||||
export function useStartTrial() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: subscriptionApi.startTrial,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useSubscribeMe() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: subscriptionApi.subscribeMe,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useChangeMyPlan() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: subscriptionApi.changeMyPlan,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCancelMySubscription() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: subscriptionApi.cancelMySubscription,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpgradeMe() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (plan: string) => subscriptionApi.upgradeMe(plan),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCancelPendingUpgrade() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: subscriptionApi.cancelPendingUpgrade,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useReactivateMe() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: subscriptionApi.reactivateMe,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user