Files
helios-evcs/apps/web/lib/api.ts

192 lines
5.6 KiB
TypeScript

const CSMS_URL = process.env.NEXT_PUBLIC_CSMS_URL ?? "http://localhost:3001";
async function apiFetch<T>(path: string, init?: RequestInit): Promise<T> {
const res = await fetch(`${CSMS_URL}${path}`, {
...init,
headers: {
"Content-Type": "application/json",
...init?.headers,
},
credentials: "include",
});
if (!res.ok) {
const text = await res.text().catch(() => res.statusText);
throw new Error(`API ${path} failed (${res.status}): ${text}`);
}
return res.json() as Promise<T>;
}
// ── Types ──────────────────────────────────────────────────────────────────
export type Stats = {
totalChargePoints: number;
onlineChargePoints: number;
activeTransactions: number;
totalIdTags: number;
todayEnergyWh: number;
};
export type ConnectorSummary = {
id: number;
connectorId: number;
status: string;
lastStatusAt: string | null;
};
export type ChargePoint = {
id: number;
chargePointIdentifier: string;
chargePointVendor: string | null;
chargePointModel: string | null;
registrationStatus: string;
lastHeartbeatAt: string | null;
lastBootNotificationAt: string | null;
feePerKwh: number;
connectors: ConnectorSummary[];
};
export type Transaction = {
id: number;
chargePointIdentifier: string | null;
connectorNumber: number | null;
idTag: string;
idTagStatus: string | null;
startTimestamp: string;
stopTimestamp: string | null;
startMeterValue: number | null;
stopMeterValue: number | null;
energyWh: number | null;
stopIdTag: string | null;
stopReason: string | null;
chargeAmount: number | null;
};
export type IdTag = {
idTag: string;
status: string;
expiryDate: string | null;
parentIdTag: string | null;
userId: string | null;
balance: number;
createdAt: string;
};
export type UserRow = {
id: string;
name: string | null;
email: string;
emailVerified: boolean;
username: string | null;
role: string | null;
banned: boolean | null;
banReason: string | null;
createdAt: string;
};
export type PaginatedTransactions = {
data: Transaction[];
total: number;
page: number;
totalPages: number;
};
// ── API functions ──────────────────────────────────────────────────────────
export const api = {
stats: {
get: () => apiFetch<Stats>("/api/stats"),
},
chargePoints: {
list: () => apiFetch<ChargePoint[]>("/api/charge-points"),
get: (id: number) => apiFetch<ChargePoint>(`/api/charge-points/${id}`),
create: (data: {
chargePointIdentifier: string;
chargePointVendor?: string;
chargePointModel?: string;
registrationStatus?: "Accepted" | "Pending" | "Rejected";
feePerKwh?: number;
}) =>
apiFetch<ChargePoint>("/api/charge-points", {
method: "POST",
body: JSON.stringify(data),
}),
update: (id: string, data: {
feePerKwh?: number;
registrationStatus?: "Accepted" | "Pending" | "Rejected";
chargePointVendor?: string;
chargePointModel?: string;
}) =>
apiFetch<ChargePoint>(`/api/charge-points/${id}`, {
method: "PATCH",
body: JSON.stringify(data),
}),
delete: (id: string) =>
apiFetch<{ success: true }>(`/api/charge-points/${id}`, { method: "DELETE" }),
},
transactions: {
list: (params?: { page?: number; limit?: number; status?: "active" | "completed" }) => {
const q = new URLSearchParams();
if (params?.page) q.set("page", String(params.page));
if (params?.limit) q.set("limit", String(params.limit));
if (params?.status) q.set("status", params.status);
const qs = q.toString();
return apiFetch<PaginatedTransactions>(`/api/transactions${qs ? "?" + qs : ""}`);
},
get: (id: number) => apiFetch<Transaction>(`/api/transactions/${id}`),
stop: (id: number) =>
apiFetch<Transaction & { online: boolean }>(`/api/transactions/${id}/stop`, {
method: "POST",
}),
delete: (id: number) =>
apiFetch<{ success: true }>(`/api/transactions/${id}`, { method: "DELETE" }),
},
idTags: {
list: () => apiFetch<IdTag[]>("/api/id-tags"),
get: (idTag: string) => apiFetch<IdTag>(`/api/id-tags/${idTag}`),
create: (data: {
idTag: string;
status?: string;
expiryDate?: string;
parentIdTag?: string;
userId?: string | null;
balance?: number;
}) => apiFetch<IdTag>("/api/id-tags", { method: "POST", body: JSON.stringify(data) }),
update: (
idTag: string,
data: {
status?: string;
expiryDate?: string | null;
parentIdTag?: string | null;
userId?: string | null;
balance?: number;
},
) => apiFetch<IdTag>(`/api/id-tags/${idTag}`, { method: "PATCH", body: JSON.stringify(data) }),
delete: (idTag: string) =>
apiFetch<{ success: true }>(`/api/id-tags/${idTag}`, { method: "DELETE" }),
},
users: {
list: () => apiFetch<UserRow[]>("/api/users"),
create: (data: {
name: string;
email: string;
password: string;
username?: string;
role?: string;
}) =>
apiFetch<{ user: UserRow }>("/api/auth/admin/create-user", {
method: "POST",
body: JSON.stringify(data),
}),
update: (
id: string,
data: {
name?: string;
username?: string | null;
role?: string;
banned?: boolean;
banReason?: string | null;
},
) => apiFetch<UserRow>(`/api/users/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
},
};