Files
Retribusi/public/dashboard/js/api.js

181 lines
5.2 KiB
JavaScript
Raw Normal View History

// public/dashboard/js/api.js
// Centralized REST API client for Btekno Retribusi Admin Dashboard
import { API_CONFIG } from './config.js';
// Export API_CONFIG untuk digunakan di file lain
export { API_CONFIG };
const API_BASE_URL = API_CONFIG.BASE_URL;
function getToken() {
return localStorage.getItem('token') || '';
}
async function apiRequest(path, options = {}) {
const url = path.startsWith('http') ? path : `${API_BASE_URL}${path}`;
const headers = {
'Content-Type': 'application/json',
// X-API-KEY dari konfigurasi backend (RETRIBUSI_API_KEY)
'X-API-KEY': API_CONFIG.API_KEY,
...(options.headers || {})
};
const token = getToken();
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const config = {
method: options.method || 'GET',
headers,
body: options.body ? JSON.stringify(options.body) : null
};
try {
const res = await fetch(url, config);
if (res.status === 401) {
// Unauthorized → clear token & redirect to login
localStorage.removeItem('token');
localStorage.removeItem('user');
// Cek apakah sudah di login page untuk menghindari redirect loop
const currentPath = window.location.pathname;
if (!currentPath.includes('index.php')) {
window.location.href = '../index.php';
}
throw new Error('Unauthorized');
}
const text = await res.text();
let json;
try {
json = text ? JSON.parse(text) : {};
} catch (e) {
json = { raw: text };
}
if (!res.ok) {
const msg = json.message || json.error || `HTTP ${res.status}`;
throw new Error(msg);
}
// Some endpoints might wrap data as { success, data, ... }
if (json && Object.prototype.hasOwnProperty.call(json, 'success') &&
Object.prototype.hasOwnProperty.call(json, 'data')) {
return json.data;
}
return json;
} catch (err) {
console.error('API error', { url, error: err });
throw err;
}
}
// Helper untuk build query string dari object params
function buildQuery(params = {}) {
const search = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== '') {
search.append(key, value);
}
});
const qs = search.toString();
return qs ? `?${qs}` : '';
}
// Typed helpers
export async function apiLogin(username, password) {
return apiRequest('/auth/v1/login', {
method: 'POST',
body: { username, password }
});
}
export async function apiGetLocations(params = {}) {
// Handle pagination: { page, limit }
const qs = buildQuery(params);
return apiRequest(`/retribusi/v1/frontend/locations${qs}`);
}
export async function apiGetGates(locationCode, params = {}) {
// Handle pagination: { page, limit, location_code }
const queryParams = { ...params };
if (locationCode) queryParams.location_code = locationCode;
const qs = buildQuery(queryParams);
return apiRequest(`/retribusi/v1/frontend/gates${qs}`);
}
export async function apiGetSummary({ date, locationCode, gateCode }) {
const qs = buildQuery({
date,
location_code: locationCode,
gate_code: gateCode
});
return apiRequest(`/retribusi/v1/dashboard/summary${qs}`);
}
export async function apiGetDaily({ startDate, endDate, locationCode }) {
const qs = buildQuery({
start_date: startDate,
end_date: endDate,
location_code: locationCode
});
return apiRequest(`/retribusi/v1/dashboard/daily${qs}`);
}
export async function apiGetByCategory({ date, locationCode, gateCode }) {
const qs = buildQuery({
date,
location_code: locationCode,
gate_code: gateCode
});
return apiRequest(`/retribusi/v1/dashboard/by-category${qs}`);
}
// Ringkasan global harian (daily_summary)
export async function apiGetSummaryDaily(params = {}) {
const qs = buildQuery(params);
return apiRequest(`/retribusi/v1/summary/daily${qs}`);
}
// Ringkasan per jam (hourly_summary)
export async function apiGetSummaryHourly(params = {}) {
const qs = buildQuery(params);
return apiRequest(`/retribusi/v1/summary/hourly${qs}`);
}
// Snapshot realtime (untuk panel live / TV wall)
export async function apiGetRealtimeSnapshot(params = {}) {
const qs = buildQuery(params);
return apiRequest(`/retribusi/v1/realtime/snapshot${qs}`);
}
// Entry events list (raw events dari mesin YOLO)
// GET /retribusi/v1/frontend/entry-events
// Parameters: page, limit, location_code, gate_code, category, start_date, end_date
export async function apiGetEntryEvents(params = {}) {
const qs = buildQuery(params);
return apiRequest(`/retribusi/v1/frontend/entry-events${qs}`);
}
// Realtime events list (history untuk SSE)
// GET /retribusi/v1/realtime/events
// Parameters: page, limit, location_code, gate_code, category, start_date, end_date
export async function apiGetRealtimeEvents(params = {}) {
const qs = buildQuery(params);
return apiRequest(`/retribusi/v1/realtime/events${qs}`);
}
// Alias untuk backward compatibility
export async function apiGetEvents(params = {}) {
return apiGetEntryEvents(params);
}
// Catatan: realtime SSE /retribusi/v1/realtime/stream akan diakses langsung via EventSource,
// bukan lewat fetch/apiRequest karena menggunakan Server-Sent Events (SSE).