feat(scholars): add multiselect and bulk actions (delete, toggle, export)
Add Set<number>-based selection state to ScholarsPage with checkboxes in both table and card views, select-all toggle, and stale-key pruning. Backend: POST /scholars/bulk-delete, POST /scholars/bulk-toggle, and GET /scholars/export?ids= filter. Service functions use user-scoped queries. Structured logging for bulk operations. Frontend: useScholarBulkActions composable extracts selection and bulk action logic. AppSelect-based action dropdown with dynamic options. Delete prompts window.confirm; enable/disable applies immediately. Export downloads filtered JSON. Includes integration tests for all bulk endpoints and frontend unit tests for selection toggle, select-all, and stale pruning.
This commit is contained in:
parent
61ac6f206f
commit
6742eff773
9 changed files with 730 additions and 79 deletions
|
|
@ -160,8 +160,30 @@ export async function clearScholarImage(
|
|||
return response.data;
|
||||
}
|
||||
|
||||
export async function exportScholarData(): Promise<DataExportPayload> {
|
||||
const response = await apiRequest<DataExportPayload>("/scholars/export", {
|
||||
export interface BulkCountResult {
|
||||
deleted_count: number;
|
||||
updated_count: number;
|
||||
}
|
||||
|
||||
export async function bulkDeleteScholars(scholarProfileIds: number[]): Promise<BulkCountResult> {
|
||||
const response = await apiRequest<BulkCountResult>("/scholars/bulk-delete", {
|
||||
method: "POST",
|
||||
body: { scholar_profile_ids: scholarProfileIds },
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function bulkToggleScholars(scholarProfileIds: number[], isEnabled: boolean): Promise<BulkCountResult> {
|
||||
const response = await apiRequest<BulkCountResult>("/scholars/bulk-toggle", {
|
||||
method: "POST",
|
||||
body: { scholar_profile_ids: scholarProfileIds, is_enabled: isEnabled },
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function exportScholarData(ids?: number[]): Promise<DataExportPayload> {
|
||||
const params = ids && ids.length > 0 ? `?ids=${ids.join(",")}` : "";
|
||||
const response = await apiRequest<DataExportPayload>(`/scholars/export${params}`, {
|
||||
method: "GET",
|
||||
});
|
||||
return response.data;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue