155 lines
4.2 KiB
TypeScript
Raw Normal View History

/**
* Subscriptions Hooks
* React hooks for subscription functionality using shared types
*/
import { useQuery } from "@tanstack/react-query";
import { apiClient, queryKeys, getDataOrDefault, getDataOrThrow, getNullableData } from "@/lib/api";
import { useAuthSession } from "@/features/auth/services";
import type { InvoiceList, Subscription, SubscriptionList } from "@customer-portal/domain/billing";
interface UseSubscriptionsOptions {
status?: string;
}
const emptySubscriptionList: SubscriptionList = {
subscriptions: [],
totalCount: 0,
};
const emptyStats = {
total: 0,
active: 0,
completed: 0,
cancelled: 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 } = useAuthSession();
return useQuery<SubscriptionList>({
queryKey: queryKeys.subscriptions.list(status ? { status } : undefined),
queryFn: async () => {
const response = await apiClient.GET<SubscriptionList>(
"/api/subscriptions",
status ? { params: { query: { status } } } : undefined
);
return toSubscriptionList(
getDataOrThrow<SubscriptionList>(response, "Failed to load subscriptions")
);
},
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
enabled: isAuthenticated,
});
}
/**
* Hook to fetch active subscriptions only
*/
export function useActiveSubscriptions() {
const { isAuthenticated } = useAuthSession();
return useQuery<Subscription[]>({
queryKey: queryKeys.subscriptions.active(),
queryFn: async () => {
const response = await apiClient.GET<Subscription[]>("/api/subscriptions/active");
return getDataOrThrow<Subscription[]>(response, "Failed to load active subscriptions");
},
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
enabled: isAuthenticated,
});
}
/**
* Hook to fetch subscription statistics
*/
export function useSubscriptionStats() {
const { isAuthenticated } = useAuthSession();
return useQuery({
queryKey: queryKeys.subscriptions.stats(),
queryFn: async () => {
const response = await apiClient.GET<typeof emptyStats>("/api/subscriptions/stats");
return getDataOrThrow<typeof emptyStats>(response, "Failed to load subscription statistics");
},
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
enabled: isAuthenticated,
});
}
/**
* Hook to fetch a specific subscription
*/
export function useSubscription(subscriptionId: number) {
const { isAuthenticated } = useAuthSession();
return useQuery<Subscription>({
queryKey: queryKeys.subscriptions.detail(String(subscriptionId)),
queryFn: async () => {
const response = await apiClient.GET<Subscription>("/api/subscriptions/{id}", {
params: { path: { id: subscriptionId } },
});
return getDataOrThrow<Subscription>(response, "Failed to load subscription details");
},
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
enabled: isAuthenticated && 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 } = useAuthSession();
return useQuery<InvoiceList>({
queryKey: queryKeys.subscriptions.invoices(subscriptionId, { page, limit }),
queryFn: async () => {
const response = await apiClient.GET<InvoiceList>("/api/subscriptions/{id}/invoices", {
params: {
path: { id: subscriptionId },
query: { page, limit },
},
});
return getDataOrThrow<InvoiceList>(response, "Failed to load subscription invoices");
},
staleTime: 60 * 1000,
gcTime: 5 * 60 * 1000,
enabled: isAuthenticated && subscriptionId > 0,
});
}