import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { router } from 'expo-router'; import { tokenManager } from '@/core/auth/token-manager'; import { disposeAllBackgroundConversationWs } from '@/features/conversation/conversation-ws-background-pool'; import { authKeys } from '@/features/auth/hooks'; import { profileApi } from './api'; import type { LegalDocType, PurgeUserDataRequest, SubmitFeedbackRequest, UpdateProfileRequest, } from './types'; const profileKeys = { all: ['profile'] as const, detail: () => [...profileKeys.all, 'detail'] as const, plans: () => [...profileKeys.all, 'plans'] as const, currentPlan: () => [...profileKeys.all, 'current-plan'] as const, quota: () => [...profileKeys.all, 'quota'] as const, faqs: () => [...profileKeys.all, 'faqs'] as const, legal: (type: LegalDocType) => [...profileKeys.all, 'legal', type] as const, } as const; // ─── Profile ─── export function useProfile() { return useQuery({ queryKey: profileKeys.detail(), queryFn: () => profileApi.fetchProfile(), }); } export function useUpdateProfile() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (body: UpdateProfileRequest) => profileApi.updateProfile(body), onSuccess: (data) => { queryClient.setQueryData(profileKeys.detail(), data); }, }); } // ─── Plans ─── export function usePlans() { return useQuery({ queryKey: profileKeys.plans(), queryFn: () => profileApi.fetchPlans(), staleTime: 10 * 60 * 1000, }); } export function useCurrentPlan() { return useQuery({ queryKey: profileKeys.currentPlan(), queryFn: () => profileApi.fetchCurrentPlan(), }); } // ─── Quota ─── export function useQuota() { return useQuery({ queryKey: profileKeys.quota(), queryFn: () => profileApi.checkQuota(), }); } // ─── FAQ ─── export function useFaqs() { return useQuery({ queryKey: profileKeys.faqs(), queryFn: () => profileApi.fetchFaqs(), staleTime: 30 * 60 * 1000, }); } // ─── Feedback ─── export function useSubmitFeedback() { return useMutation({ mutationFn: (body: SubmitFeedbackRequest) => profileApi.submitFeedback(body), }); } /** * 永久清空服务端业务数据;成功后服务端会吊销所有 refresh token, * 因此仅清本地会话并跳转登录(不再调用 logout 接口)。 */ export function usePurgeUserData() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (body: PurgeUserDataRequest) => profileApi.purgeUserData(body), onSuccess: async () => { disposeAllBackgroundConversationWs(); await tokenManager.clearTokens(); queryClient.clear(); queryClient.setQueryData(authKeys.tokenCheck, false); router.replace('/(auth)/login'); }, }); } // ─── Legal ─── export function useLegalDoc( type: LegalDocType, options?: { enabled?: boolean }, ) { return useQuery({ queryKey: profileKeys.legal(type), queryFn: () => profileApi.fetchLegalDoc(type), staleTime: Infinity, enabled: options?.enabled ?? true, }); }