/** * Subscriptions Hooks * React hooks for subscription functionality using shared types */ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { useAuthSession } from "@/features/auth/services/auth.store"; import { apiClient } from "@/core/api"; import type { Subscription, SubscriptionList, InvoiceList } from "@customer-portal/domain"; interface UseSubscriptionsOptions { status?: string; } /** * Hook to fetch all subscriptions */ export function useSubscriptions(options: UseSubscriptionsOptions = {}) { const { status } = options; const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: ["subscriptions", status], queryFn: async () => { const params = new URLSearchParams({ ...(status && { status }), }); const response = await apiClient.GET( "/subscriptions", status ? { params: { query: { status } } } : undefined ); if (!response.data) { return [] as Subscription[]; } return response.data as SubscriptionList | Subscription[]; }, staleTime: 5 * 60 * 1000, // 5 minutes gcTime: 10 * 60 * 1000, // 10 minutes enabled: isAuthenticated && hasValidToken, }); } /** * Hook to fetch active subscriptions only */ export function useActiveSubscriptions() { const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: ["subscriptions", "active"], queryFn: async () => { if (!hasValidToken) { throw new Error("Authentication required"); } const response = await apiClient.GET("/subscriptions/active"); return (response.data ?? []) as Subscription[]; }, staleTime: 5 * 60 * 1000, // 5 minutes gcTime: 10 * 60 * 1000, // 10 minutes enabled: isAuthenticated && hasValidToken, }); } /** * Hook to fetch subscription statistics */ export function useSubscriptionStats() { const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery<{ total: number; active: number; suspended: number; cancelled: number; pending: number; }>({ queryKey: ["subscriptions", "stats"], queryFn: async () => { if (!hasValidToken) { throw new Error("Authentication required"); } const response = await apiClient.GET("/subscriptions/stats"); return (response.data ?? { total: 0, active: 0, suspended: 0, cancelled: 0, pending: 0, }) as { total: number; active: number; suspended: number; cancelled: number; pending: number; }; }, staleTime: 5 * 60 * 1000, // 5 minutes gcTime: 10 * 60 * 1000, // 10 minutes enabled: isAuthenticated && hasValidToken, }); } /** * Hook to fetch a specific subscription */ export function useSubscription(subscriptionId: number) { const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: ["subscription", subscriptionId], queryFn: async () => { if (!hasValidToken) { throw new Error("Authentication required"); } const response = await apiClient.GET("/subscriptions/{id}", { params: { path: { id: subscriptionId } }, }); if (!response.data) { throw new Error("Subscription not found"); } return response.data as Subscription; }, staleTime: 5 * 60 * 1000, // 5 minutes gcTime: 10 * 60 * 1000, // 10 minutes enabled: isAuthenticated && hasValidToken, }); } /** * Hook to fetch subscription invoices */ export function useSubscriptionInvoices( subscriptionId: number, options: { page?: number; limit?: number } = {} ) { const { page = 1, limit = 10 } = options; const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: ["subscription-invoices", subscriptionId, page, limit], queryFn: async () => { if (!hasValidToken) { throw new Error("Authentication required"); } const response = await apiClient.GET("/subscriptions/{id}/invoices", { params: { path: { id: subscriptionId }, query: { page, limit }, }, }); return ( response.data ?? { invoices: [], pagination: { page, totalPages: 0, totalItems: 0, }, } ) as InvoiceList; }, staleTime: 60 * 1000, // 1 minute gcTime: 5 * 60 * 1000, // 5 minutes enabled: isAuthenticated && hasValidToken && !!subscriptionId, }); } /** * Hook to perform subscription actions (suspend, resume, cancel, etc.) */ export function useSubscriptionAction() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, action }: { id: number; action: string }) => { await apiClient.POST("/subscriptions/{id}/actions", { params: { path: { id } }, body: { action }, }); }, onSuccess: (_, { id }) => { // Invalidate relevant queries after successful action void queryClient.invalidateQueries({ queryKey: ["subscriptions"] }); void queryClient.invalidateQueries({ queryKey: ["subscription", id] }); }, }); }