geo/frontend/lib/hooks/use-onboarding-data.ts

130 lines
3.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 新用户引导页面数据获取 Hook
*
* 封装引导状态检查的 SWR 请求 + 品牌创建的 mutation替代手动 useState + useEffect 模式。
* - 引导状态检查mount 时自动获取
* - 品牌创建mutation由用户交互触发
*/
import { useCallback } from "react";
import { useApi, useApiMutation } from "./use-api";
import type { SWRConfiguration } from "swr";
import { getSession } from "next-auth/react";
import type { Session } from "next-auth";
import { monitoringApi } from "@/lib/api/monitoring";
interface OnboardingStatusResponse {
completed: boolean;
}
interface CreateBrandResponse {
brand_id: string;
}
export interface CreateBrandPayload {
name: string;
competitors: string[];
platforms: string[];
frequency: "daily" | "weekly" | "monthly";
}
export interface UseOnboardingDataReturn {
/** 引导状态数据 */
onboardingStatus: OnboardingStatusResponse | undefined;
/** 是否已完成引导 */
isCompleted: boolean;
/** 是否正在加载 */
isLoading: boolean;
/** 错误信息 */
error: Error | undefined;
/** 刷新引导状态 */
refresh: () => void;
/** 创建品牌 */
createBrand: (data: CreateBrandPayload) => Promise<string | null>;
/** 是否正在创建品牌 */
isCreatingBrand: boolean;
/** 创建品牌错误 */
mutationError: Error | undefined;
/** 创建监控任务 */
createMonitoringTask: (
brandId: string,
platforms: string[],
frequency: string
) => Promise<void>;
}
export interface UseOnboardingDataOptions {
/** SWR 配置(用于测试时禁用重试等) */
swrOptions?: SWRConfiguration;
}
export function useOnboardingData(
options?: UseOnboardingDataOptions
): UseOnboardingDataReturn {
const swrOptions = options?.swrOptions;
// 引导状态检查
const {
data: onboardingStatus,
isLoading,
error,
refresh,
} = useApi<OnboardingStatusResponse>("/api/v1/onboarding/status", swrOptions);
const isCompleted = onboardingStatus?.completed ?? false;
// 创建品牌mutation
const {
trigger: createBrandTrigger,
isMutating: isCreatingBrand,
error: mutationError,
} = useApiMutation<CreateBrandResponse, CreateBrandPayload>(
"/api/v1/onboarding/brand",
"POST"
);
const createBrand = useCallback(
async (data: CreateBrandPayload): Promise<string | null> => {
const result = await createBrandTrigger(data);
return result?.brand_id ?? null;
},
[createBrandTrigger]
);
const createMonitoringTask = useCallback(
async (
brandId: string,
platforms: string[],
frequency: string
): Promise<void> => {
try {
const session = await getSession();
const token = (session as Session)?.accessToken;
if (!token) return;
for (const platform of platforms) {
await monitoringApi.createTask(token, {
brand_id: brandId,
platform,
query_keywords: frequency,
});
}
} catch {
// silent
}
},
[]
);
return {
onboardingStatus,
isCompleted,
isLoading,
error,
refresh,
createBrand,
isCreatingBrand,
mutationError,
createMonitoringTask,
};
}