Browse Source

feat(hooks): 新增隐私相关 hooks(6 个)

- usePrivacyDetailSetting:按 id 拉取隐私二级设置并切换开关
- useDndSetting:勿扰模式读取与更新
- useKeywordBlock:关键词屏蔽的读取与增删
- useAccountCancel:注销前置信息拉取与提交
- useDeleteAllData:可删除分类拉取与提交
- useLegalDocument:隐私政策 / 用户协议正文拉取

均基于 useAsyncData 封装,统一在 src/hooks/index.ts 导出
master
doublex001 2 months ago
parent
commit
00ce854445
  1. 31
      src/hooks/useAccountCancel.ts
  2. 31
      src/hooks/useDeleteAllData.ts
  3. 34
      src/hooks/useDndSetting.ts
  4. 47
      src/hooks/useKeywordBlock.ts
  5. 24
      src/hooks/useLegalDocument.ts
  6. 37
      src/hooks/usePrivacyDetailSetting.ts

31
src/hooks/useAccountCancel.ts

@ -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 };
}

31
src/hooks/useDeleteAllData.ts

@ -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 };
}

34
src/hooks/useDndSetting.ts

@ -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 };
}

47
src/hooks/useKeywordBlock.ts

@ -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 };
}

24
src/hooks/useLegalDocument.ts

@ -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 };
}

37
src/hooks/usePrivacyDetailSetting.ts

@ -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…
Cancel
Save