Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions frontend/src/services/benefitsApi.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import axios from 'axios';

const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001/api/v1';

function authHeaders() {
const token = localStorage.getItem('payd_auth_token');
return token ? { Authorization: `Bearer ${token}` } : undefined;
}
import api from '../utils/api';

export interface DraftPayslipLine {
source: 'deduction_rule' | 'tax_rule';
Expand All @@ -29,11 +22,8 @@ export interface DraftPayslip {
}

export const getMyDeductionsDraftPayslip = async (): Promise<DraftPayslip> => {
const { data } = await axios.get<{ success: boolean; data: DraftPayslip }>(
`${API_BASE_URL}/benefits/me/deductions`,
{
headers: authHeaders(),
}
const { data } = await api.get<{ success: boolean; data: DraftPayslip }>(
'/v1/benefits/me/deductions'
);

return data.data;
Expand Down
56 changes: 18 additions & 38 deletions frontend/src/services/cashFlowForecastApi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import axios, { type AxiosError } from 'axios';

const API_BASE_URL =
(import.meta.env.VITE_API_BASE_URL as string | undefined) || 'http://localhost:3001';
import { isAxiosError, type AxiosError } from 'axios';
import api from '../utils/api';

export interface HistoricalPayrollData {
period: string;
Expand Down Expand Up @@ -98,15 +96,12 @@ export interface AlertsResponse {
*/
export const getForecast = async (params: ForecastParams): Promise<CashFlowForecast> => {
try {
const response = await axios.get<ForecastResponse>(`${API_BASE_URL}/api/cash-flow/forecast`, {
const response = await api.get<ForecastResponse>('/cash-flow/forecast', {
params: {
forecastDays: params.forecastDays || 90,
distributionAccount: params.distributionAccount,
assetIssuer: params.assetIssuer,
},
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`,
},
});

if (!response.data.success) {
Expand All @@ -115,7 +110,7 @@ export const getForecast = async (params: ForecastParams): Promise<CashFlowForec

return response.data.data;
} catch (error) {
if (axios.isAxiosError(error)) {
if (isAxiosError(error)) {
const axiosError = error as AxiosError<{ message?: string }>;
const errorMessage =
(axiosError.response?.data as { message?: string } | undefined)?.message ||
Expand All @@ -139,25 +134,19 @@ export const getHistoricalData = async (
averages: { weekly: number; biweekly: number; monthly: number };
}> => {
try {
const response = await axios.get<HistoricalDataResponse>(
`${API_BASE_URL}/api/cash-flow/historical`,
{
params: {
monthsBack: monthsBack || 6,
},
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`,
},
}
);
const response = await api.get<HistoricalDataResponse>('/cash-flow/historical', {
params: {
monthsBack: monthsBack || 6,
},
});

if (!response.data.success) {
throw new Error('Failed to fetch historical data');
}

return response.data.data;
} catch (error) {
if (axios.isAxiosError(error)) {
if (isAxiosError(error)) {
const axiosError = error as AxiosError<{ message?: string }>;
const errorMessage =
(axiosError.response?.data as { message?: string } | undefined)?.message ||
Expand All @@ -178,25 +167,19 @@ export const getProjections = async (
forecastDays?: number
): Promise<UpcomingPayrollProjection[]> => {
try {
const response = await axios.get<ProjectionsResponse>(
`${API_BASE_URL}/api/cash-flow/projections`,
{
params: {
forecastDays: forecastDays || 90,
},
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`,
},
}
);
const response = await api.get<ProjectionsResponse>('/cash-flow/projections', {
params: {
forecastDays: forecastDays || 90,
},
});

if (!response.data.success) {
throw new Error('Failed to fetch projections');
}

return response.data.data;
} catch (error) {
if (axios.isAxiosError(error)) {
if (isAxiosError(error)) {
const axiosError = error as AxiosError<{ message?: string }>;
const errorMessage =
(axiosError.response?.data as { message?: string } | undefined)?.message ||
Expand All @@ -220,15 +203,12 @@ export const getAlerts = async (
summary: { totalAlerts: number; criticalAlerts: number; warningAlerts: number };
}> => {
try {
const response = await axios.get<AlertsResponse>(`${API_BASE_URL}/api/cash-flow/alerts`, {
const response = await api.get<AlertsResponse>('/cash-flow/alerts', {
params: {
forecastDays: params.forecastDays || 90,
distributionAccount: params.distributionAccount,
assetIssuer: params.assetIssuer,
},
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`,
},
});

if (!response.data.success) {
Expand All @@ -237,7 +217,7 @@ export const getAlerts = async (

return response.data.data;
} catch (error) {
if (axios.isAxiosError(error)) {
if (isAxiosError(error)) {
const axiosError = error as AxiosError<{ message?: string }>;
const errorMessage =
(axiosError.response?.data as { message?: string } | undefined)?.message ||
Expand Down
33 changes: 9 additions & 24 deletions frontend/src/services/forecastApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import axios from 'axios';

const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001/api/v1';
import api from '../utils/api';

export interface ForecastLiquidity {
status: 'green' | 'yellow' | 'red';
Expand Down Expand Up @@ -52,39 +50,26 @@ export interface LiquiditySettings {
alertEmails?: string[];
}

function authHeaders() {
const token = localStorage.getItem('payd_auth_token');
return token ? { Authorization: `Bearer ${token}` } : undefined;
}

export const getForecast = async (monthsForward: number = 6): Promise<ForecastResponse> => {
const { data } = await axios.get<{ success: boolean; data: ForecastResponse }>(
`${API_BASE_URL}/forecast`,
{
params: { monthsForward },
headers: authHeaders(),
}
);
const { data } = await api.get<{ success: boolean; data: ForecastResponse }>('/v1/forecast', {
params: { monthsForward },
});
return data.data;
};

export const getLiquiditySettings = async (): Promise<LiquiditySettings | null> => {
const { data } = await axios.get<{ success: boolean; data: LiquiditySettings | null }>(
`${API_BASE_URL}/forecast/settings`,
{
headers: authHeaders(),
}
const { data } = await api.get<{ success: boolean; data: LiquiditySettings | null }>(
'/v1/forecast/settings'
);
return data.data;
};

export const updateLiquiditySettings = async (
input: LiquiditySettings
): Promise<LiquiditySettings> => {
const { data } = await axios.put<{ success: boolean; data: LiquiditySettings }>(
`${API_BASE_URL}/forecast/settings`,
input,
{ headers: authHeaders() }
const { data } = await api.put<{ success: boolean; data: LiquiditySettings }>(
'/v1/forecast/settings',
input
);
return data.data;
};
49 changes: 16 additions & 33 deletions frontend/src/services/transactionHistory.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import api from '../utils/api';
import { contractService } from './contracts';

const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000';

export interface HistoryFilters {
search: string;
status: string;
Expand Down Expand Up @@ -36,15 +35,6 @@ function asString(value: unknown, fallback = ''): string {
return fallback;
}

function toQuery(params: Record<string, string | number | undefined>): string {
const query = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => {
if (value === undefined || value === '') return;
query.set(key, String(value));
});
return query.toString();
}

function normalizeClassicItem(row: Record<string, unknown>): TimelineItem {
const txHash = asString(row.tx_hash, '') || null;
return {
Expand Down Expand Up @@ -82,23 +72,18 @@ export async function fetchHistoryPage(options: {
filters: HistoryFilters;
}): Promise<{ items: TimelineItem[]; hasMore: boolean }> {
const { page, limit, filters } = options;
const query = toQuery({
page,
limit,
status: filters.status || undefined,
employee: filters.employee || undefined,
asset: filters.asset || undefined,
startDate: filters.startDate || undefined,
endDate: filters.endDate || undefined,
search: filters.search || undefined,
const { data: auditPayload } = await api.get<AuditResponse>('/v1/audit', {
params: {
page,
limit,
status: filters.status || undefined,
employee: filters.employee || undefined,
asset: filters.asset || undefined,
startDate: filters.startDate || undefined,
endDate: filters.endDate || undefined,
search: filters.search || undefined,
},
});

const auditResponse = await fetch(`${API_BASE_URL}/api/v1/audit?${query}`);
if (!auditResponse.ok) {
throw new Error(`Failed to fetch audit records (${auditResponse.status})`);
}

const auditPayload = (await auditResponse.json()) as AuditResponse;
const classicItems = (auditPayload.data || []).map(normalizeClassicItem);

await contractService.initialize();
Expand All @@ -112,13 +97,11 @@ export async function fetchHistoryPage(options: {
await Promise.all(
contractIds.map(async (contractId) => {
try {
const eventResponse = await fetch(
`${API_BASE_URL}/api/events/${contractId}?page=1&limit=10`
);
if (!eventResponse.ok) return;
const payload = (await eventResponse.json()) as {
const { data: payload } = await api.get<{
data?: Array<Record<string, unknown>>;
};
}>(`/events/${contractId}`, {
params: { page: 1, limit: 10 },
});
(payload.data || []).forEach((row) => {
contractItems.push(normalizeContractItem(contractId, row));
});
Expand Down
22 changes: 8 additions & 14 deletions frontend/src/services/withdrawal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
* Handles anchor discovery, withdrawal initiation, and transaction polling.
*/

import axios from 'axios';

const API_BASE_URL = (import.meta.env.VITE_API_URL as string) || 'http://localhost:3000/api';
import api from '../utils/api';

export interface AnchorInfo {
domain: string;
Expand Down Expand Up @@ -60,10 +58,9 @@ const withdrawalService = {
*/
getAvailableAnchors: async (assetCode: string = 'ORGUSD'): Promise<AnchorInfo[]> => {
try {
const response = await axios.get<{ anchors: AnchorInfo[] }>(
`${API_BASE_URL}/withdrawal/anchors`,
{ params: { assetCode } }
);
const response = await api.get<{ anchors: AnchorInfo[] }>('/withdrawal/anchors', {
params: { assetCode },
});
return response.data.anchors;
} catch {
// Mock data for development until backend is ready
Expand Down Expand Up @@ -101,10 +98,7 @@ const withdrawalService = {
*/
initiateWithdrawal: async (request: WithdrawalRequest): Promise<WithdrawalResponse> => {
try {
const response = await axios.post<WithdrawalResponse>(
`${API_BASE_URL}/withdrawal/initiate`,
request
);
const response = await api.post<WithdrawalResponse>('/withdrawal/initiate', request);
return response.data;
} catch {
// Mock response for development
Expand All @@ -125,8 +119,8 @@ const withdrawalService = {
anchorDomain: string
): Promise<WithdrawalTransaction> => {
try {
const response = await axios.get<WithdrawalTransaction>(
`${API_BASE_URL}/withdrawal/status/${transactionId}`,
const response = await api.get<WithdrawalTransaction>(
`/withdrawal/status/${transactionId}`,
{ params: { anchorDomain } }
);
return response.data;
Expand All @@ -149,7 +143,7 @@ const withdrawalService = {
*/
cancelWithdrawal: async (transactionId: string): Promise<void> => {
try {
await axios.post(`${API_BASE_URL}/withdrawal/cancel`, { transactionId });
await api.post('/withdrawal/cancel', { transactionId });
} catch {
// Mock success for development
console.log('Mock: Withdrawal cancelled', transactionId);
Expand Down