/** * TDD Phase 2: GREEN - Minimal code to pass tests * * This Hook implements works search functionality: * - Supports keyword search * - Supports category filter * - Supports pagination * - Only executes query when keyword is provided */ import { root } from '@repo/core' import { TemplateGenerationController } from '@repo/sdk' import { useCallback, useEffect, useState } from 'react' import { type ApiError } from '@/lib/types' import { handleError } from './use-error' // Type definitions export type WorksCategory = '全部' | '萌宠' | '写真' | '合拍' export interface UseWorksSearchParams { keyword: string category?: WorksCategory page?: number limit?: number } export interface WorksSearchResult { id: string createdAt: Date template: { id: string name: string } status: string duration: number } export interface WorksSearchResponse { data: WorksSearchResult[] total: number page: number limit: number totalPages: number } /** * Hook for searching works with keyword and category filtering * * @param params - Search parameters including keyword, category, page, and limit * @returns Object with data, loading state, error, and refetch function * * @example * ```tsx * const { data, works, isLoading, error } = useWorksSearch({ * keyword: '测试', * category: '萌宠', * page: 1, * limit: 20 * }) * ``` */ export function useWorksSearch(params: UseWorksSearchParams) { const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [data, setData] = useState(undefined) const { keyword, category, page = 1, limit = 20 } = params // Auto-execute search when params change useEffect(() => { const execute = async () => { // Only execute query when keyword has content const trimmedKeyword = keyword?.trim() || '' if (!trimmedKeyword) { setData(undefined) setError(null) return } setLoading(true) setError(null) // Build API params - only include category if it's not "全部" const apiParams = { keyword: trimmedKeyword, ...(category && category !== '全部' && { category }), page, limit, } const templateGeneration = root.get(TemplateGenerationController) const { data: result, error: err } = await handleError(async () => await templateGeneration.list(apiParams) ) if (err) { setError(err) setLoading(false) return } setData(result as WorksSearchResponse) setLoading(false) } execute() }, [keyword, category, page, limit]) const refetch = useCallback(() => { const execute = async () => { const trimmedKeyword = keyword?.trim() || '' if (!trimmedKeyword) { setData(undefined) setError(null) return { data: undefined, error: null } } setLoading(true) setError(null) const apiParams = { keyword: trimmedKeyword, ...(category && category !== '全部' && { category }), page, limit, } const templateGeneration = root.get(TemplateGenerationController) const { data: result, error: err } = await handleError(async () => await templateGeneration.list(apiParams) ) if (err) { setError(err) setLoading(false) return { data: undefined, error: err } } setData(result as WorksSearchResponse) setLoading(false) return { data: result as WorksSearchResponse, error: null } } return execute() }, [keyword, category, page, limit]) return { data, works: data?.data || [], isLoading: loading, error, refetch, } }