/** * Subscriptions Hooks * React hooks for subscription functionality using shared types */ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { apiClient, queryKeys } from "@/core/api"; import { useAuthSession } from "@/features/auth/services/auth.store"; import type { InvoiceList, Subscription, SubscriptionList } from "@customer-portal/domain"; interface UseSubscriptionsOptions { status?: string; } const emptySubscriptionList: SubscriptionList = { subscriptions: [], totalCount: 0, }; const emptyStats = { total: 0, active: 0, suspended: 0, cancelled: 0, pending: 0, }; const emptyInvoiceList: InvoiceList = { invoices: [], pagination: { page: 1, totalItems: 0, totalPages: 0, }, }; function toSubscriptionList( payload?: SubscriptionList | Subscription[] | null ): SubscriptionList { if (!payload) { return emptySubscriptionList; } if (Array.isArray(payload)) { return { subscriptions: payload, totalCount: payload.length, }; } return payload; } /** * Hook to fetch all subscriptions */ export function useSubscriptions(options: UseSubscriptionsOptions = {}) { const { status } = options; const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: queryKeys.subscriptions.list(status ? { status } : {}), queryFn: async () => { const response = await apiClient.GET( "/subscriptions", status ? { params: { query: { status } } } : undefined ); return toSubscriptionList(response.data); }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, enabled: isAuthenticated && hasValidToken, }); } /** * Hook to fetch active subscriptions only */ export function useActiveSubscriptions() { const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: [...queryKeys.subscriptions.all, "active"] as const, queryFn: async () => { const response = await apiClient.GET("/subscriptions/active"); return response.data ?? []; }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, enabled: isAuthenticated && hasValidToken, }); } /** * Hook to fetch subscription statistics */ export function useSubscriptionStats() { const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: queryKeys.subscriptions.stats(), queryFn: async () => { const response = await apiClient.GET("/subscriptions/stats"); return response.data ?? emptyStats; }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, enabled: isAuthenticated && hasValidToken, }); } /** * Hook to fetch a specific subscription */ export function useSubscription(subscriptionId: number) { const { isAuthenticated, hasValidToken } = useAuthSession(); return useQuery({ queryKey: queryKeys.subscriptions.detail(String(subscriptionId)), queryFn: async () => { const response = await apiClient.GET("/subscriptions/{id}", { params: { path: { id: subscriptionId } }, }); if (!response.data) { throw new Error("Subscription not found"); } return response.data; }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, enabled: isAuthenticated && hasValidToken && subscriptionId > 0, }); } /** * 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: queryKeys.subscriptions.invoices(subscriptionId, { page, limit }), queryFn: async () => { const response = await apiClient.GET("/subscriptions/{id}/invoices", { params: { path: { id: subscriptionId }, query: { page, limit }, }, }); if (!response.data) { return { ...emptyInvoiceList, pagination: { ...emptyInvoiceList.pagination, page, }, }; } return response.data; }, staleTime: 60 * 1000, gcTime: 5 * 60 * 1000, enabled: isAuthenticated && hasValidToken && subscriptionId > 0, }); } /** * 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: async () => { await queryClient.invalidateQueries({ queryKey: queryKeys.subscriptions.all }); }, }); }