feat: add frontend subscription page - M4 (refs #55)

This commit is contained in:
Eric Gullickson
2026-01-18 16:37:10 -06:00
parent e7461a4836
commit 94d1c677bc
17 changed files with 1312 additions and 5 deletions

View File

@@ -0,0 +1,76 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useAuth0 } from '@auth0/auth0-react';
import { subscriptionApi } from '../api/subscription.api';
import toast from 'react-hot-toast';
export const useSubscription = () => {
const { isAuthenticated, isLoading } = useAuth0();
return useQuery({
queryKey: ['subscription'],
queryFn: () => subscriptionApi.getSubscription(),
enabled: isAuthenticated && !isLoading,
staleTime: 5 * 60 * 1000,
retry: (failureCount, error: unknown) => {
const err = error as { response?: { status?: number } };
if (err?.response?.status === 401 && failureCount < 3) return true;
return false;
},
});
};
export const useCheckout = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: subscriptionApi.checkout,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['subscription'] });
queryClient.invalidateQueries({ queryKey: ['user-profile'] });
toast.success('Subscription upgraded successfully');
},
onError: (error: unknown) => {
const err = error as { response?: { data?: { error?: string } } };
toast.error(err.response?.data?.error || 'Failed to upgrade subscription');
},
});
};
export const useCancelSubscription = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: subscriptionApi.cancel,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['subscription'] });
toast.success('Subscription scheduled for cancellation');
},
onError: (error: unknown) => {
const err = error as { response?: { data?: { error?: string } } };
toast.error(err.response?.data?.error || 'Failed to cancel subscription');
},
});
};
export const useReactivateSubscription = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: subscriptionApi.reactivate,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['subscription'] });
toast.success('Subscription reactivated');
},
onError: (error: unknown) => {
const err = error as { response?: { data?: { error?: string } } };
toast.error(err.response?.data?.error || 'Failed to reactivate subscription');
},
});
};
export const useInvoices = () => {
const { isAuthenticated, isLoading } = useAuth0();
return useQuery({
queryKey: ['invoices'],
queryFn: () => subscriptionApi.getInvoices(),
enabled: isAuthenticated && !isLoading,
staleTime: 5 * 60 * 1000,
});
};