Browse Source
- usePrivacyDetailSetting:按 id 拉取隐私二级设置并切换开关 - useDndSetting:勿扰模式读取与更新 - useKeywordBlock:关键词屏蔽的读取与增删 - useAccountCancel:注销前置信息拉取与提交 - useDeleteAllData:可删除分类拉取与提交 - useLegalDocument:隐私政策 / 用户协议正文拉取 均基于 useAsyncData 封装,统一在 src/hooks/index.ts 导出master
6 changed files with 204 additions and 0 deletions
@ -0,0 +1,31 @@ |
|||||
|
/** |
||||
|
* 账号注销 hook,获取前置信息并提交注销申请。 |
||||
|
*/ |
||||
|
import { useCallback } from 'react'; |
||||
|
import { fetchAccountCancel, submitAccountCancel } from '../api'; |
||||
|
import type { AccountCancelData } from '../types'; |
||||
|
import { useAsyncData } from './useAsyncData'; |
||||
|
|
||||
|
export interface AccountCancelState { |
||||
|
data: AccountCancelData | null; |
||||
|
loading: boolean; |
||||
|
error: Error | null; |
||||
|
refresh: () => void; |
||||
|
submit: (reason: string) => Promise<{ success: boolean; message: string }>; |
||||
|
} |
||||
|
|
||||
|
export function useAccountCancel(): AccountCancelState { |
||||
|
const fetcher = useCallback(async (): Promise<AccountCancelData> => fetchAccountCancel(), []); |
||||
|
const { data, loading, error, refresh } = useAsyncData(fetcher); |
||||
|
|
||||
|
const submit = useCallback(async (reason: string) => { |
||||
|
try { |
||||
|
return await submitAccountCancel(reason); |
||||
|
} catch (err) { |
||||
|
console.error('[useAccountCancel] submit error', err); |
||||
|
return { success: false, message: '提交失败,请稍后重试' }; |
||||
|
} |
||||
|
}, []); |
||||
|
|
||||
|
return { data: data ?? null, loading, error, refresh, submit }; |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
/** |
||||
|
* 删除全部数据 hook,获取可删除分类并提交删除申请。 |
||||
|
*/ |
||||
|
import { useCallback } from 'react'; |
||||
|
import { fetchDeleteAllData, submitDeleteData } from '../api'; |
||||
|
import type { DeleteAllData } from '../types'; |
||||
|
import { useAsyncData } from './useAsyncData'; |
||||
|
|
||||
|
export interface DeleteAllDataState { |
||||
|
data: DeleteAllData | null; |
||||
|
loading: boolean; |
||||
|
error: Error | null; |
||||
|
refresh: () => void; |
||||
|
submit: (categoryIds: string[]) => Promise<{ success: boolean; message: string }>; |
||||
|
} |
||||
|
|
||||
|
export function useDeleteAllData(): DeleteAllDataState { |
||||
|
const fetcher = useCallback(async (): Promise<DeleteAllData> => fetchDeleteAllData(), []); |
||||
|
const { data, loading, error, refresh } = useAsyncData(fetcher); |
||||
|
|
||||
|
const submit = useCallback(async (categoryIds: string[]) => { |
||||
|
try { |
||||
|
return await submitDeleteData(categoryIds); |
||||
|
} catch (err) { |
||||
|
console.error('[useDeleteAllData] submit error', err); |
||||
|
return { success: false, message: '提交失败,请稍后重试' }; |
||||
|
} |
||||
|
}, []); |
||||
|
|
||||
|
return { data: data ?? null, loading, error, refresh, submit }; |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
/** |
||||
|
* 勿扰模式设置 hook。 |
||||
|
*/ |
||||
|
import { useCallback } from 'react'; |
||||
|
import { fetchDndSetting, updateDndSetting } from '../api'; |
||||
|
import type { DndSetting } from '../types'; |
||||
|
import { useAsyncData } from './useAsyncData'; |
||||
|
|
||||
|
export interface DndSettingState { |
||||
|
setting: DndSetting | null; |
||||
|
loading: boolean; |
||||
|
error: Error | null; |
||||
|
refresh: () => void; |
||||
|
update: (payload: Partial<DndSetting>) => Promise<void>; |
||||
|
} |
||||
|
|
||||
|
export function useDndSetting(): DndSettingState { |
||||
|
const fetcher = useCallback(async (): Promise<DndSetting> => fetchDndSetting(), []); |
||||
|
const { data, loading, error, refresh } = useAsyncData(fetcher); |
||||
|
|
||||
|
const update = useCallback( |
||||
|
async (payload: Partial<DndSetting>) => { |
||||
|
try { |
||||
|
await updateDndSetting(payload); |
||||
|
refresh(); |
||||
|
} catch (err) { |
||||
|
console.error('[useDndSetting] update error', err); |
||||
|
} |
||||
|
}, |
||||
|
[refresh], |
||||
|
); |
||||
|
|
||||
|
return { setting: data ?? null, loading, error, refresh, update }; |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
/** |
||||
|
* 关键词屏蔽设置 hook,支持关键词的增删。 |
||||
|
*/ |
||||
|
import { useCallback } from 'react'; |
||||
|
import { fetchKeywordBlock, addBlockKeyword, removeBlockKeyword } from '../api'; |
||||
|
import type { KeywordBlockSetting } from '../types'; |
||||
|
import { useAsyncData } from './useAsyncData'; |
||||
|
|
||||
|
export interface KeywordBlockState { |
||||
|
setting: KeywordBlockSetting | null; |
||||
|
loading: boolean; |
||||
|
error: Error | null; |
||||
|
refresh: () => void; |
||||
|
addKeyword: (keyword: string) => Promise<void>; |
||||
|
removeKeyword: (keyword: string) => Promise<void>; |
||||
|
} |
||||
|
|
||||
|
export function useKeywordBlock(): KeywordBlockState { |
||||
|
const fetcher = useCallback(async (): Promise<KeywordBlockSetting> => fetchKeywordBlock(), []); |
||||
|
const { data, loading, error, refresh } = useAsyncData(fetcher); |
||||
|
|
||||
|
const addKeyword = useCallback( |
||||
|
async (keyword: string) => { |
||||
|
try { |
||||
|
await addBlockKeyword(keyword); |
||||
|
refresh(); |
||||
|
} catch (err) { |
||||
|
console.error('[useKeywordBlock] add error', err); |
||||
|
} |
||||
|
}, |
||||
|
[refresh], |
||||
|
); |
||||
|
|
||||
|
const removeKeyword = useCallback( |
||||
|
async (keyword: string) => { |
||||
|
try { |
||||
|
await removeBlockKeyword(keyword); |
||||
|
refresh(); |
||||
|
} catch (err) { |
||||
|
console.error('[useKeywordBlock] remove error', err); |
||||
|
} |
||||
|
}, |
||||
|
[refresh], |
||||
|
); |
||||
|
|
||||
|
return { setting: data ?? null, loading, error, refresh, addKeyword, removeKeyword }; |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
/** |
||||
|
* 法律文档(隐私政策 / 用户协议)hook,按 id 拉取正文。 |
||||
|
*/ |
||||
|
import { useCallback } from 'react'; |
||||
|
import { fetchLegalDocument } from '../api'; |
||||
|
import type { LegalDocument } from '../types'; |
||||
|
import { useAsyncData } from './useAsyncData'; |
||||
|
|
||||
|
export interface LegalDocumentState { |
||||
|
doc: LegalDocument | null; |
||||
|
loading: boolean; |
||||
|
error: Error | null; |
||||
|
refresh: () => void; |
||||
|
} |
||||
|
|
||||
|
export function useLegalDocument(id: string): LegalDocumentState { |
||||
|
const fetcher = useCallback( |
||||
|
async (): Promise<LegalDocument | null> => fetchLegalDocument(id), |
||||
|
[id], |
||||
|
); |
||||
|
const { data, loading, error, refresh } = useAsyncData(fetcher); |
||||
|
|
||||
|
return { doc: data ?? null, loading, error, refresh }; |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
/** |
||||
|
* 隐私二级设置(开关类子页)hook,按页面 id 拉取并切换开关。 |
||||
|
*/ |
||||
|
import { useCallback } from 'react'; |
||||
|
import { fetchPrivacyDetailSetting, updatePrivacyDetailSetting } from '../api'; |
||||
|
import type { PrivacyDetailSetting } from '../types'; |
||||
|
import { useAsyncData } from './useAsyncData'; |
||||
|
|
||||
|
export interface PrivacyDetailState { |
||||
|
detail: PrivacyDetailSetting | null; |
||||
|
loading: boolean; |
||||
|
error: Error | null; |
||||
|
refresh: () => void; |
||||
|
toggle: (optionId: string, enabled: boolean) => Promise<void>; |
||||
|
} |
||||
|
|
||||
|
export function usePrivacyDetailSetting(id: string): PrivacyDetailState { |
||||
|
const fetcher = useCallback( |
||||
|
async (): Promise<PrivacyDetailSetting | null> => fetchPrivacyDetailSetting(id), |
||||
|
[id], |
||||
|
); |
||||
|
const { data, loading, error, refresh } = useAsyncData(fetcher); |
||||
|
|
||||
|
const toggle = useCallback( |
||||
|
async (optionId: string, enabled: boolean) => { |
||||
|
try { |
||||
|
await updatePrivacyDetailSetting(id, optionId, enabled); |
||||
|
refresh(); |
||||
|
} catch (err) { |
||||
|
console.error('[usePrivacyDetailSetting] toggle error', err); |
||||
|
} |
||||
|
}, |
||||
|
[id, refresh], |
||||
|
); |
||||
|
|
||||
|
return { detail: data ?? null, loading, error, refresh, toggle }; |
||||
|
} |
||||
Loading…
Reference in new issue