таски готовы
This commit is contained in:
83
frontend/src/lib/api/reports.js
Normal file
83
frontend/src/lib/api/reports.js
Normal file
@@ -0,0 +1,83 @@
|
||||
// [DEF:frontend.src.lib.api.reports:Module]
|
||||
// @TIER: CRITICAL
|
||||
// @SEMANTICS: frontend, api_client, reports, wrapper
|
||||
// @PURPOSE: Wrapper-based reports API client for list/detail retrieval without direct native fetch usage.
|
||||
// @LAYER: Infra
|
||||
// @RELATION: DEPENDS_ON -> [DEF:api_module]
|
||||
// @INVARIANT: Uses existing api wrapper methods and returns structured errors for UI-state mapping.
|
||||
|
||||
import { api } from '../api.js';
|
||||
|
||||
// [DEF:buildReportQueryString:Function]
|
||||
// @PURPOSE: Build query string for reports list endpoint from filter options.
|
||||
// @PRE: options is an object with optional report query fields.
|
||||
// @POST: Returns URL query string without leading '?'.
|
||||
export function buildReportQueryString(options = {}) {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (options.page != null) params.append('page', String(options.page));
|
||||
if (options.page_size != null) params.append('page_size', String(options.page_size));
|
||||
|
||||
if (Array.isArray(options.task_types) && options.task_types.length > 0) {
|
||||
params.append('task_types', options.task_types.join(','));
|
||||
}
|
||||
if (Array.isArray(options.statuses) && options.statuses.length > 0) {
|
||||
params.append('statuses', options.statuses.join(','));
|
||||
}
|
||||
|
||||
if (options.time_from) params.append('time_from', options.time_from);
|
||||
if (options.time_to) params.append('time_to', options.time_to);
|
||||
if (options.search) params.append('search', options.search);
|
||||
if (options.sort_by) params.append('sort_by', options.sort_by);
|
||||
if (options.sort_order) params.append('sort_order', options.sort_order);
|
||||
|
||||
return params.toString();
|
||||
}
|
||||
// [/DEF:buildReportQueryString:Function]
|
||||
|
||||
// [DEF:normalizeApiError:Function]
|
||||
// @PURPOSE: Convert unknown API exceptions into deterministic UI-consumable error objects.
|
||||
// @PRE: error may be Error/string/object.
|
||||
// @POST: Returns structured error object.
|
||||
export function normalizeApiError(error) {
|
||||
const message =
|
||||
(error && typeof error.message === 'string' && error.message) ||
|
||||
(typeof error === 'string' && error) ||
|
||||
'Failed to load reports';
|
||||
|
||||
return {
|
||||
message,
|
||||
code: 'REPORTS_API_ERROR',
|
||||
retryable: true
|
||||
};
|
||||
}
|
||||
// [/DEF:normalizeApiError:Function]
|
||||
|
||||
// [DEF:getReports:Function]
|
||||
// @PURPOSE: Fetch unified report list using existing request wrapper.
|
||||
// @PRE: valid auth context for protected endpoint.
|
||||
// @POST: Returns parsed payload or structured error for UI-state mapping.
|
||||
export async function getReports(options = {}) {
|
||||
try {
|
||||
const query = buildReportQueryString(options);
|
||||
return await api.fetchApi(`/reports${query ? `?${query}` : ''}`);
|
||||
} catch (error) {
|
||||
throw normalizeApiError(error);
|
||||
}
|
||||
}
|
||||
// [/DEF:getReports:Function]
|
||||
|
||||
// [DEF:getReportDetail:Function]
|
||||
// @PURPOSE: Fetch one report detail by report_id.
|
||||
// @PRE: reportId is non-empty string; valid auth context.
|
||||
// @POST: Returns parsed detail payload or structured error object.
|
||||
export async function getReportDetail(reportId) {
|
||||
try {
|
||||
return await api.fetchApi(`/reports/${reportId}`);
|
||||
} catch (error) {
|
||||
throw normalizeApiError(error);
|
||||
}
|
||||
}
|
||||
// [/DEF:getReportDetail:Function]
|
||||
|
||||
// [/DEF:frontend.src.lib.api.reports:Module]
|
||||
Reference in New Issue
Block a user