177 lines
5.0 KiB
TypeScript
Raw Normal View History

/**
* Subscriptions Hooks
* React hooks for subscription functionality using shared types
*/
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useAuthStore } 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 { tokens, isAuthenticated } = useAuthStore();
return useQuery<SubscriptionList | Subscription[]>({
queryKey: ["subscriptions", status],
queryFn: async () => {
if (!tokens?.accessToken) {
throw new Error("Authentication required");
}
const params = new URLSearchParams({
...(status && { status }),
});
const res = await apiClient.get<SubscriptionList | Subscription[]>(
`/subscriptions?${params}`
);
return res.data as SubscriptionList | Subscription[];
},
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
enabled: isAuthenticated && !!tokens?.accessToken,
});
}
/**
* Hook to fetch active subscriptions only
*/
export function useActiveSubscriptions() {
const { tokens, isAuthenticated } = useAuthStore();
return useQuery<Subscription[]>({
queryKey: ["subscriptions", "active"],
queryFn: async () => {
if (!tokens?.accessToken) {
throw new Error("Authentication required");
}
const res = await apiClient.get<Subscription[]>(`/subscriptions/active`);
return res.data as Subscription[];
},
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
enabled: isAuthenticated && !!tokens?.accessToken,
});
}
/**
* Hook to fetch subscription statistics
*/
export function useSubscriptionStats() {
const { tokens, isAuthenticated } = useAuthStore();
return useQuery<{
total: number;
active: number;
suspended: number;
cancelled: number;
pending: number;
}>({
queryKey: ["subscriptions", "stats"],
queryFn: async () => {
if (!tokens?.accessToken) {
throw new Error("Authentication required");
}
const res = await apiClient.get<{
total: number;
active: number;
suspended: number;
cancelled: number;
pending: number;
}>(`/subscriptions/stats`);
return res.data 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 && !!tokens?.accessToken,
});
}
/**
* Hook to fetch a specific subscription
*/
export function useSubscription(subscriptionId: number) {
const { tokens, isAuthenticated } = useAuthStore();
return useQuery<Subscription>({
queryKey: ["subscription", subscriptionId],
queryFn: async () => {
if (!tokens?.accessToken) {
throw new Error("Authentication required");
}
const res = await apiClient.get<Subscription>(`/subscriptions/${subscriptionId}`);
return res.data as Subscription;
},
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
enabled: isAuthenticated && !!tokens?.accessToken,
});
}
/**
* Hook to fetch subscription invoices
*/
export function useSubscriptionInvoices(
subscriptionId: number,
options: { page?: number; limit?: number } = {}
) {
const { page = 1, limit = 10 } = options;
const { tokens, isAuthenticated } = useAuthStore();
return useQuery<InvoiceList>({
queryKey: ["subscription-invoices", subscriptionId, page, limit],
queryFn: async () => {
if (!tokens?.accessToken) {
throw new Error("Authentication required");
}
const params = new URLSearchParams({
page: page.toString(),
limit: limit.toString(),
});
const res = await apiClient.get<InvoiceList>(
`/subscriptions/${subscriptionId}/invoices?${params}`
);
return unwrap(res) as InvoiceList;
},
staleTime: 60 * 1000, // 1 minute
gcTime: 5 * 60 * 1000, // 5 minutes
enabled: isAuthenticated && !!tokens?.accessToken && !!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 }) => {
const res = await apiClient.post(`/subscriptions/${id}/actions`, { action });
return unwrap(res);
},
onSuccess: (_, { id }) => {
// Invalidate relevant queries after successful action
void queryClient.invalidateQueries({ queryKey: ["subscriptions"] });
void queryClient.invalidateQueries({ queryKey: ["subscription", id] });
},
});
}