First passenger and back office portal commit

This commit is contained in:
Stephanos A
2026-05-31 13:15:44 +03:00
parent a0b5eb1e92
commit 5059a1fe58
181 changed files with 14249 additions and 13949 deletions

View File

@@ -0,0 +1,29 @@
import { apiClient } from '@/lib/api-client';
import { Booking, BookingFilters } from '@/types';
import { PaginatedResponse } from '@edr/types';
export const bookingsApi = {
getAll: (filters?: BookingFilters) => {
const params = new URLSearchParams();
if (filters?.status) params.append('status', filters.status);
if (filters?.dateFrom) params.append('dateFrom', filters.dateFrom);
if (filters?.dateTo) params.append('dateTo', filters.dateTo);
if (filters?.search) params.append('search', filters.search);
if (filters?.page) params.append('page', filters.page.toString());
if (filters?.pageSize) params.append('pageSize', filters.pageSize.toString());
return apiClient.get<PaginatedResponse<Booking>>(`/bookings?${params.toString()}`);
},
getById: (id: string) => {
return apiClient.get<Booking>(`/bookings/${id}`);
},
updateStatus: (id: string, status: string) => {
return apiClient.patch<Booking>(`/bookings/${id}/status`, { status });
},
cancel: (id: string, reason?: string) => {
return apiClient.post<Booking>(`/bookings/${id}/cancel`, { reason });
},
};

View File

@@ -0,0 +1,16 @@
import { apiClient } from '@/lib/api-client';
import { DashboardStats, RevenueData } from '@/types';
export const dashboardApi = {
getStats: () => {
return apiClient.get<DashboardStats>('/dashboard/stats');
},
getRevenueChart: (days: number = 30) => {
return apiClient.get<RevenueData[]>(`/dashboard/revenue?days=${days}`);
},
getRecentBookings: (limit: number = 10) => {
return apiClient.get<any[]>(`/dashboard/recent-bookings?limit=${limit}`);
},
};

View File

@@ -0,0 +1,338 @@
import { apiClient } from '@/lib/api-client';
import { PaginatedResponse } from '@edr/types';
// Bookings API
export const bookingsApi = {
getAll: async (params?: any) => {
const cleanParams = Object.fromEntries(
Object.entries(params || {}).filter(([_, value]) => value !== '' && value !== undefined && value !== null)
);
const query = new URLSearchParams(cleanParams).toString();
const response = await apiClient.get<any>(`/bookings${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/bookings/${id}`),
cancel: (id: string, data?: any) => apiClient.post<any>(`/bookings/${id}/cancel`, data),
modify: (id: string, data: any) => apiClient.patch<any>(`/bookings/${id}`, data),
};
// Passengers API
export const passengersApi = {
getAll: async (params?: any) => {
const cleanParams = Object.fromEntries(
Object.entries(params || {}).filter(([_, value]) => value !== '' && value !== undefined && value !== null)
);
const query = new URLSearchParams(cleanParams).toString();
const response = await apiClient.get<any>(`/passengers${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/passengers/${id}`),
verify: (nationalId: string) => apiClient.post<any>('/passengers/verify-fayda', { nationalId }),
};
// Stations API
export const stationsApi = {
getAll: async (params?: any) => {
const cleanParams = Object.fromEntries(
Object.entries(params || {}).filter(([_, value]) => value !== '' && value !== undefined && value !== null)
);
const query = new URLSearchParams(cleanParams).toString();
const response = await apiClient.get<any>(`/stations${query ? `?${query}` : ''}`);
// Handle wrapped response: { success, data: [...], timestamp }
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/stations/${id}`),
create: (data: any) => apiClient.post<any>('/stations', data),
update: (id: string, data: any) => apiClient.patch<any>(`/stations/${id}`, data),
delete: (id: string) => apiClient.delete(`/stations/${id}`),
};
// Fleet API
export const fleetApi = {
getTrains: async (params?: any) => {
const cleanParams = Object.fromEntries(
Object.entries(params || {}).filter(([_, value]) => value !== '' && value !== undefined && value !== null)
);
const query = new URLSearchParams(cleanParams).toString();
const response = await apiClient.get<any>(`/fleet/trains${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getCoaches: async (params?: any) => {
const cleanParams = Object.fromEntries(
Object.entries(params || {}).filter(([_, value]) => value !== '' && value !== undefined && value !== null)
);
const query = new URLSearchParams(cleanParams).toString();
const response = await apiClient.get<any>(`/fleet/coaches${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
createTrain: (data: any) => apiClient.post<any>('/fleet/trains', data),
updateTrain: (id: string, data: any) => apiClient.patch<any>(`/fleet/trains/${id}`, data),
deleteTrain: (id: string) => apiClient.delete(`/fleet/trains/${id}`),
createCoach: (data: any) => apiClient.post<any>('/fleet/coaches', data),
updateCoach: (id: string, data: any) => apiClient.patch<any>(`/fleet/coaches/${id}`, data),
deleteCoach: (id: string) => apiClient.delete(`/fleet/coaches/${id}`),
};
// Schedules API
export const schedulesApi = {
getAll: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/schedules${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/schedules/${id}`),
create: (data: any) => apiClient.post<any>('/schedules', data),
update: (id: string, data: any) => apiClient.patch<any>(`/schedules/${id}`, data),
delete: (id: string) => apiClient.delete(`/schedules/${id}`),
updateStatus: (id: string, status: string) => apiClient.patch<any>(`/schedules/${id}/status`, { status }),
assignCoaches: (scheduleId: string, coaches: Array<{ coachId: string; positionNumber: number }>) =>
apiClient.post<any>(`/schedules/${scheduleId}/coaches`, { coaches }),
getAssignedCoaches: (scheduleId: string) => apiClient.get<any>(`/schedules/${scheduleId}/coaches`),
removeCoachAssignment: (scheduleId: string, coachId: string) =>
apiClient.delete(`/schedules/${scheduleId}/coaches/${coachId}`),
};
// Seats API
export const seatsApi = {
getBySchedule: (scheduleId: string) => apiClient.get<any>(`/seats/schedule/${scheduleId}`),
hold: (data: any) => apiClient.post<any>('/seats/hold', data),
release: (holdId: string) => apiClient.delete(`/seats/hold/${holdId}`),
block: (seatId: string, data: any) => apiClient.post<any>(`/seats/${seatId}/block`, data),
unblock: (seatId: string) => apiClient.delete(`/seats/${seatId}/block`),
};
// Payments API
export const paymentsApi = {
getAll: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/payments${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/payments/${id}`),
refund: (id: string, data: any) => apiClient.post<any>(`/payments/${id}/refund`, data),
getProviders: () => apiClient.get<any[]>('/payments/providers'),
};
// Tickets API
export const ticketsApi = {
getAll: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/tickets${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/tickets/${id}`),
validate: (ticketId: string, data: any) => apiClient.post<any>(`/tickets/${ticketId}/validate`, data),
regenerate: (ticketId: string) => apiClient.post<any>(`/tickets/${ticketId}/regenerate`),
};
// Agents API
export const agentsApi = {
getAll: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/agents${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/agents/${id}`),
create: (data: any) => apiClient.post<any>('/agents', data),
update: (id: string, data: any) => apiClient.patch<any>(`/agents/${id}`, data),
getShifts: (agentId: string) => apiClient.get<any[]>(`/agents/${agentId}/shifts`),
openShift: (agentId: string, data: any) => apiClient.post<any>(`/agents/${agentId}/shifts/open`, data),
closeShift: (shiftId: string, data: any) => apiClient.post<any>(`/agents/shifts/${shiftId}/close`, data),
getCommissions: (agentId: string) => apiClient.get<any[]>(`/agents/${agentId}/commissions`),
};
// Loyalty API
export const loyaltyApi = {
getAccounts: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/loyalty/accounts${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getAccount: (passengerId: string) => apiClient.get<any>(`/loyalty/accounts/${passengerId}`),
adjustPoints: (accountId: string, data: any) => apiClient.post<any>(`/loyalty/accounts/${accountId}/adjust`, data),
getRewards: () => apiClient.get<any[]>('/loyalty/rewards'),
createReward: (data: any) => apiClient.post<any>('/loyalty/rewards', data),
};
// Wallet API
export const walletApi = {
getAccounts: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/wallet/accounts${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getAccount: (passengerId: string) => apiClient.get<any>(`/wallet/accounts/${passengerId}`),
adjustBalance: (accountId: string, data: any) => apiClient.post<any>(`/wallet/accounts/${accountId}/adjust`, data),
getLedger: (accountId: string) => apiClient.get<any[]>(`/wallet/accounts/${accountId}/ledger`),
};
// Promotions API
export const promotionsApi = {
getAll: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/promos${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/promos/${id}`),
create: (data: any) => apiClient.post<any>('/promos', data),
update: (id: string, data: any) => apiClient.patch<any>(`/promos/${id}`, data),
delete: (id: string) => apiClient.delete(`/promos/${id}`),
};
// Support API
export const supportApi = {
getConversations: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/support/conversations${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getConversation: (id: string) => apiClient.get<any>(`/support/conversations/${id}`),
updateStatus: (id: string, status: string) => apiClient.patch<any>(`/support/conversations/${id}/status`, { status }),
sendMessage: (conversationId: string, data: any) => apiClient.post<any>(`/support/conversations/${conversationId}/messages`, data),
getFaqs: () => apiClient.get<any[]>('/support/faqs'),
createFaq: (data: any) => apiClient.post<any>('/support/faqs', data),
};
// Notifications API
export const notificationsApi = {
getTemplates: () => apiClient.get<any[]>('/notifications/templates'),
createTemplate: (data: any) => apiClient.post<any>('/notifications/templates', data),
updateTemplate: (id: string, data: any) => apiClient.patch<any>(`/notifications/templates/${id}`, data),
send: (data: any) => apiClient.post<any>('/notifications/send', data),
getHistory: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/notifications/history${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
};
// Fraud API
export const fraudApi = {
getAlerts: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/fraud/alerts${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
acknowledgeAlert: (id: string) => apiClient.patch<any>(`/fraud/alerts/${id}/acknowledge`),
getRules: () => apiClient.get<any[]>('/fraud/rules'),
updateRule: (id: string, data: any) => apiClient.patch<any>(`/fraud/rules/${id}`, data),
blockUser: (userId: string, data: any) => apiClient.post<any>(`/fraud/users/${userId}/block`, data),
};
// Verifayda API
export const verifaydaApi = {
getVerifications: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/passengers/verifications${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
verify: (nationalId: string) => apiClient.post<any>('/passengers/verify-fayda', { nationalId }),
getStats: () => apiClient.get<any>('/passengers/verification-stats'),
};
// Audit API
export const auditApi = {
getLogs: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/audit/logs${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getLog: (id: string) => apiClient.get<any>(`/audit/logs/${id}`),
};
// Live Tracking API
export const liveApi = {
getTrips: () => apiClient.get<any[]>('/live/trips'),
getTrip: (tripId: string) => apiClient.get<any>(`/live/trips/${tripId}`),
updateLocation: (tripId: string, data: any) => apiClient.post<any>(`/live/trips/${tripId}/location`, data),
getCrowdSignals: () => apiClient.get<any[]>('/live/crowd-signals'),
};
// Seat Classes API
export const seatClassesApi = {
getAll: () => apiClient.get<any[]>('/seat-classes'),
getById: (id: string) => apiClient.get<any>(`/seat-classes/${id}`),
create: (data: any) => apiClient.post<any>('/seat-classes', data),
update: (id: string, data: any) => apiClient.patch<any>(`/seat-classes/${id}`, data),
delete: (id: string) => apiClient.delete(`/seat-classes/${id}`),
};
// Food & Dining API
export const foodApi = {
getCategories: () => apiClient.get<any[]>('/food/categories'),
getMenuItems: (scheduleId: string) => apiClient.get<any[]>(`/food/menu/${scheduleId}`),
getOrders: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/food/orders${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
updateOrderStatus: (orderId: string, status: string) => apiClient.patch<any>(`/food/orders/${orderId}/status`, { status }),
createMenuItem: (data: any) => apiClient.post<any>('/food/menu-items', data),
};
// Reports API
export const reportsApi = {
getOperationalReports: async (params?: any) => {
const query = new URLSearchParams(params).toString();
const response = await apiClient.get<any>(`/reports/operational${query ? `?${query}` : ''}`);
if (response?.data) {
return Array.isArray(response.data) ? { items: response.data } : response;
}
return Array.isArray(response) ? { items: response } : response;
},
getRevenue: (params?: any) => apiClient.get<any>('/reports/revenue', { params }),
getOccupancy: (params?: any) => apiClient.get<any>('/reports/occupancy', { params }),
};

View File

@@ -0,0 +1,23 @@
import { apiClient } from '@/lib/api-client';
import { PassengerFilters } from '@/types';
import { Passenger, PaginatedResponse } from '@edr/types';
export const passengersApi = {
getAll: (filters?: PassengerFilters) => {
const params = new URLSearchParams();
if (filters?.search) params.append('search', filters.search);
if (filters?.verified !== undefined) params.append('verified', filters.verified.toString());
if (filters?.page) params.append('page', filters.page.toString());
if (filters?.pageSize) params.append('pageSize', filters.pageSize.toString());
return apiClient.get<PaginatedResponse<Passenger.IPassenger>>(`/passengers?${params.toString()}`);
},
getById: (id: string) => {
return apiClient.get<Passenger.IPassenger>(`/passengers/${id}`);
},
update: (id: string, data: Partial<Passenger.IPassenger>) => {
return apiClient.patch<Passenger.IPassenger>(`/passengers/${id}`, data);
},
};

View File

@@ -0,0 +1,64 @@
import { apiClient } from '@/lib/api-client';
import { Route, Trip, FareRule } from '@/types';
import { PaginatedResponse } from '@edr/types';
export const routesApi = {
getAll: async () => {
const response = await apiClient.get<any>('/routes');
console.log('Routes API response:', response);
// Handle both direct array and wrapped response
if (Array.isArray(response)) {
return { items: response };
}
if (response?.data && Array.isArray(response.data)) {
return { items: response.data };
}
if (response?.items) {
return response;
}
return { items: response || [] };
},
getById: (id: string) => {
return apiClient.get<Route>(`/routes/${id}`);
},
create: (data: any) => {
console.log('Creating route with data:', JSON.stringify(data, null, 2));
return apiClient.post<Route>('/routes', data);
},
update: (id: string, data: Partial<Route>) => {
return apiClient.patch<Route>(`/routes/${id}`, data);
},
delete: (id: string) => {
return apiClient.delete(`/routes/${id}`);
},
getFareRules: (routeId: string) => {
return apiClient.get<FareRule[]>(`/routes/${routeId}/fare-rules`);
},
updateFareRule: (routeId: string, ruleId: string, data: Partial<FareRule>) => {
return apiClient.patch<FareRule>(`/routes/${routeId}/fare-rules/${ruleId}`, data);
},
};
export const tripsApi = {
getAll: (filters?: any) => {
const params = new URLSearchParams();
if (filters?.status) params.append('status', filters.status);
if (filters?.date) params.append('date', filters.date);
return apiClient.get<PaginatedResponse<Trip>>(`/schedules?${params.toString()}`);
},
getById: (id: string) => {
return apiClient.get<Trip>(`/schedules/${id}`);
},
updateStatus: (id: string, status: string) => {
return apiClient.patch<Trip>(`/schedules/${id}/status`, { status });
},
};