Files
expo-popcore-app/hooks/use-works-search.ts
imeepos e1340fa101 feat: 实现 API 接口对接功能 (删除作品、作品搜索、修改密码)
按照 TDD 规范完成三个核心功能的接口对接:

## 新增功能

### 1. 删除作品功能 (app/generationRecord.tsx)
- 新增 use-template-generation-actions.ts hook
- 支持单个删除和批量删除作品
- 删除确认对话框
- 删除成功后自动刷新列表
- 完整的错误处理和加载状态

### 2. 作品搜索功能 (app/searchWorksResults.tsx)
- 新增 use-works-search.ts hook
- 替换模拟数据为真实 SDK 接口
- 支持关键词搜索和分类筛选
- 支持分页加载
- 完整的加载、错误、空结果状态处理

### 3. 修改密码功能 (app/changePassword.tsx)
- 新增 use-change-password.ts hook
- 使用 Better Auth 的 changePassword API
- 客户端表单验证(密码长度、确认密码匹配等)
- 成功后自动返回并提示

## 技术实现
- 严格遵循 TDD 规范(先写测试,后写实现)
- 新增 3 个 hooks 和对应的单元测试
- 更新中英文翻译文件
- 更新 jest.setup.js 添加必要的 mock

## 文档
- 新增 api_integration_report.md - API 对接分析报告
- 新增 api_integration_development_plan.md - 开发计划和完成汇总

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 19:15:24 +08:00

105 lines
2.5 KiB
TypeScript

/**
* TDD Phase 2: GREEN - Minimal code to pass tests
*
* This Hook implements works search functionality:
* - Uses @tanstack/react-query for data fetching
* - Supports keyword search
* - Supports category filter
* - Supports pagination
* - Only executes query when keyword is provided
*/
import { useQuery } from '@tanstack/react-query'
import { root } from '@repo/core'
import { TemplateGenerationController } from '@repo/sdk'
import { useCallback } from 'react'
// Type definitions
export interface UseWorksSearchParams {
keyword: string
category?: '全部' | '萌宠' | '写真' | '合拍'
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 Query result 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 { keyword, category, page = 1, limit = 20 } = params
// Build query key - "全部" category should not be included
const queryKey = [
'worksSearch',
keyword,
category === '全部' ? undefined : category,
page,
limit,
] as const
// Build API params - only include category if it's not "全部"
const apiParams = {
keyword,
...(category && category !== '全部' && { category }),
page,
limit,
}
// Query function
const queryFn = useCallback(async (): Promise<WorksSearchResponse> => {
const controller = root.get(TemplateGenerationController)
const result = await controller.list(apiParams)
return result as WorksSearchResponse
}, [keyword, category, page, limit])
// Execute query only when keyword has content
const trimmedKeyword = keyword?.trim() || ''
const isEnabled = !!trimmedKeyword
const query = useQuery({
queryKey,
queryFn,
enabled: isEnabled,
})
return {
data: query.data,
works: query.data?.data || [],
isLoading: query.isLoading,
error: query.error,
refetch: query.refetch,
}
}