diff --git a/src/app/[locale]/providers.tsx b/src/app/[locale]/providers.tsx index 8f751af..76ebae3 100644 --- a/src/app/[locale]/providers.tsx +++ b/src/app/[locale]/providers.tsx @@ -1,7 +1,6 @@ 'use client'; import { ActiveThemeProvider } from '@/components/layout/active-theme-provider'; -import { PaymentProvider } from '@/components/layout/payment-provider'; import { QueryProvider } from '@/components/providers/query-provider'; import { TooltipProvider } from '@/components/ui/tooltip'; import { websiteConfig } from '@/config/website'; @@ -63,9 +62,7 @@ export function Providers({ children, locale }: ProvidersProps) { > - - {children} - + {children} diff --git a/src/components/dashboard/sidebar-user.tsx b/src/components/dashboard/sidebar-user.tsx index ca6bfe1..6a0831a 100644 --- a/src/components/dashboard/sidebar-user.tsx +++ b/src/components/dashboard/sidebar-user.tsx @@ -23,7 +23,6 @@ import { useLocalePathname, useLocaleRouter } from '@/i18n/navigation'; import { LOCALES, routing } from '@/i18n/routing'; import { authClient } from '@/lib/auth-client'; import { useLocaleStore } from '@/stores/locale-store'; -import { usePaymentStore } from '@/stores/payment-store'; import type { User } from 'better-auth'; import { ChevronsUpDown, @@ -55,7 +54,6 @@ export function SidebarUser({ user, className }: SidebarUserProps) { const pathname = useLocalePathname(); const params = useParams(); const { currentLocale, setCurrentLocale } = useLocaleStore(); - const { resetState } = usePaymentStore(); const [, startTransition] = useTransition(); const t = useTranslations(); @@ -81,8 +79,7 @@ export function SidebarUser({ user, className }: SidebarUserProps) { fetchOptions: { onSuccess: () => { console.log('sign out success'); - // Reset payment state on sign out - resetState(); + // TanStack Query automatically handles cache invalidation on sign out router.replace('/'); }, onError: (error) => { @@ -100,7 +97,7 @@ export function SidebarUser({ user, className }: SidebarUserProps) { { setMounted(true); }, []); // Don't show the upgrade card if the user has a lifetime membership or a subscription - const isMember = currentPlan?.isLifetime || !!subscription; + const isMember = + paymentData?.currentPlan?.isLifetime || !!paymentData?.subscription; if (!mounted || isLoading || isMember) { return null; diff --git a/src/components/layout/payment-provider.tsx b/src/components/layout/payment-provider.tsx deleted file mode 100644 index 60d6a47..0000000 --- a/src/components/layout/payment-provider.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client'; - -import { authClient } from '@/lib/auth-client'; -import { usePaymentStore } from '@/stores/payment-store'; -import { useEffect } from 'react'; - -/** - * Payment provider component - * - * This component is responsible for initializing the payment state - * by fetching the current user's subscription and payment information when the app loads. - */ -export function PaymentProvider({ children }: { children: React.ReactNode }) { - const { fetchPayment } = usePaymentStore(); - const { data: session } = authClient.useSession(); - - useEffect(() => { - if (session?.user) { - fetchPayment(session.user); - } - }, [session?.user, fetchPayment]); - - return <>{children}; -} diff --git a/src/components/layout/user-button-mobile.tsx b/src/components/layout/user-button-mobile.tsx index 21e8afd..b5573e3 100644 --- a/src/components/layout/user-button-mobile.tsx +++ b/src/components/layout/user-button-mobile.tsx @@ -13,7 +13,6 @@ import { import { getAvatarLinks } from '@/config/avatar-config'; import { LocaleLink, useLocaleRouter } from '@/i18n/navigation'; import { authClient } from '@/lib/auth-client'; -import { usePaymentStore } from '@/stores/payment-store'; import type { User } from 'better-auth'; import { LogOutIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; @@ -29,8 +28,6 @@ export function UserButtonMobile({ user }: UserButtonProps) { const avatarLinks = getAvatarLinks(); const localeRouter = useLocaleRouter(); const [open, setOpen] = useState(false); - const { resetState } = usePaymentStore(); - const closeDrawer = () => { setOpen(false); }; @@ -40,8 +37,7 @@ export function UserButtonMobile({ user }: UserButtonProps) { fetchOptions: { onSuccess: () => { console.log('sign out success'); - // Reset payment state on sign out - resetState(); + // TanStack Query automatically handles cache invalidation on sign out localeRouter.replace('/'); }, onError: (error) => { @@ -64,7 +60,7 @@ export function UserButtonMobile({ user }: UserButtonProps) { diff --git a/src/components/layout/user-button.tsx b/src/components/layout/user-button.tsx index d48bc0c..cd0dfd8 100644 --- a/src/components/layout/user-button.tsx +++ b/src/components/layout/user-button.tsx @@ -12,7 +12,6 @@ import { getAvatarLinks } from '@/config/avatar-config'; import { websiteConfig } from '@/config/website'; import { useLocaleRouter } from '@/i18n/navigation'; import { authClient } from '@/lib/auth-client'; -import { usePaymentStore } from '@/stores/payment-store'; import type { User } from 'better-auth'; import { LogOutIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; @@ -29,15 +28,12 @@ export function UserButton({ user }: UserButtonProps) { const avatarLinks = getAvatarLinks(); const localeRouter = useLocaleRouter(); const [open, setOpen] = useState(false); - const { resetState } = usePaymentStore(); - const handleSignOut = async () => { await authClient.signOut({ fetchOptions: { onSuccess: () => { console.log('sign out success'); - // Reset payment state on sign out - resetState(); + // TanStack Query automatically handles cache invalidation on sign out localeRouter.replace('/'); }, onError: (error) => { diff --git a/src/components/settings/billing/billing-card.tsx b/src/components/settings/billing/billing-card.tsx index 6483906..28e619d 100644 --- a/src/components/settings/billing/billing-card.tsx +++ b/src/components/settings/billing/billing-card.tsx @@ -14,7 +14,7 @@ import { import { Skeleton } from '@/components/ui/skeleton'; import { getPricePlans } from '@/config/price-config'; import { useMounted } from '@/hooks/use-mounted'; -import { usePayment } from '@/hooks/use-payment'; +import { useCurrentPlan } from '@/hooks/use-payment-query'; import { LocaleLink, useLocaleRouter } from '@/i18n/navigation'; import { authClient } from '@/lib/auth-client'; import { formatDate } from '@/lib/formatter'; @@ -33,34 +33,37 @@ export default function BillingCard() { const hasHandledSession = useRef(false); const mounted = useMounted(); - const { - isLoading: isLoadingPayment, - error: loadPaymentError, - subscription, - currentPlan: currentPlanFromStore, - fetchPayment, - } = usePayment(); - // Get user session for customer ID const { data: session, isPending: isLoadingSession } = authClient.useSession(); const currentUser = session?.user; + // TanStack Query hook for current plan and subscription + const { + data: paymentData, + isLoading: isLoadingPayment, + error: loadPaymentError, + refetch: refetchPayment, + } = useCurrentPlan(currentUser?.id); + + const currentPlan = paymentData?.currentPlan; + const subscription = paymentData?.subscription; + // Get price plans with translations - must be called here to maintain hook order const pricePlans = getPricePlans(); const plans = Object.values(pricePlans); - // Convert current plan from store to a plan with translations - const currentPlan = currentPlanFromStore - ? plans.find((plan) => plan.id === currentPlanFromStore?.id) + // Convert current plan to a plan with translations + const currentPlanWithTranslations = currentPlan + ? plans.find((plan) => plan.id === currentPlan?.id) : null; - const isFreePlan = currentPlan?.isFree || false; - const isLifetimeMember = currentPlan?.isLifetime || false; + const isFreePlan = currentPlanWithTranslations?.isFree || false; + const isLifetimeMember = currentPlanWithTranslations?.isLifetime || false; // Get subscription price details const currentPrice = subscription && - currentPlan?.prices.find( + currentPlanWithTranslations?.prices.find( (price) => price.priceId === subscription?.priceId ); @@ -77,8 +80,8 @@ export default function BillingCard() { // Retry payment data fetching const handleRetry = useCallback(() => { // console.log('handleRetry, refetch payment info'); - fetchPayment(true); - }, [fetchPayment]); + refetchPayment(); + }, [refetchPayment]); // Check for payment success and show success message useEffect(() => { @@ -132,7 +135,9 @@ export default function BillingCard() { {t('currentPlan.description')} -
{loadPaymentError}
+
+ {loadPaymentError?.message} +